Page MenuHomePhabricator

Upgrading: Mid 2020 Changes to "arc land"
Open, NormalPublic

Description

Default Merge Strategy

IMPORTANT: If you use Git with history.immutable set to true, arc land will no longer select the "merge" strategy by default. You must configure arc.land.strategy if you wish to use the "merge" strategy by default.

Previously, arc land had two flags to select merge strategies (--squash and --merge), and selected a default strategy based on the value of the history.immutable configuration setting, which defaults to true in Mercurial and false in Git.

The "squash" strategy collapses multiple local commits into a single final commit when publishing them, and produces a linear published history (but discards local checkpoints at publish time).

The "merge" strategy always creates a merge commit joining local commits to the published branch, and retains local checkpoint commits at publish time (but produces a nonlinear history).

The default strategy is now always "squash". Strategies are now selected with --strategy <strategy>. A different default strategy can now be configured with arc.land.strategy in configuration.

Here's an overview of the change:

VCShistory.immutableOld Default StrategyNew Default Strategy
Git<Not Configured>squashsquash
Gitfalsesquashsquash
Gittruemergesquash
Mercurial<Not Configured>N/Asquash
Mercurialfalsesquashsquash
MercurialtrueN/Asquash

The cells marked N/A are because Mercurial attempted to select merge as a strategy, but arc land did not support this strategy in Mercurial.

Here is how the flags have changed, specifically:

Old FlagNew Flag
--merge --strategy merge
--squash--strategy squash

The effect of these flags has not changed.

Conceptually, Mercurial was once more philosophically opposed to mutating history (e.g., upstream Mercurial had no history mutation commands in ~2012 when many of these workflows were first written) and many Mercurial users echoed this philosophy when selecting workflows. Over time, this philosophy has softened and Mercurial is now more philosophically comfortable with mutating unpublished history, with concepts like "phases" and "evolve" in the Mercurial mainline.

The old history.immutable configuration setting applied to several different behaviors which users may reasonably want to vary separately. Instead, arc is moving toward configuring/prompting for these behaviors separately, so you can allow certain kinds of history mutation and forbid others.

Phabricator is developed with the "squash" strategy and the official upstream recommendation is that you should use the "squash" strategy, based on a belief that the value of a simple linear history greatly outweighs the value of retaining checkpoint commits through publishing under all reasonable development conditions. However, these changes to arc land also improve support for the "merge" strategy if you disagree with this recommendation -- just make sure you update your configuration to select it!

(For now, when arc land selects "squash" but would previously have selected "merge", the workflow will abort. You can configure "arc.land.strategy" explicitly to bypass this check. This check will be removed in some future version of Arcanist and the workflow will continue forward using the "squash" strategy.)

Mercurial/SVN and Git/SVN

Support for Mercurial/SVN (that is: Mercurial repositories backed by Subversion repositories using the "HgSubversion" extension) has been removed.

Support for Git/SVN (that is: Git repositories backed by Subversion repositories using the "git-svn" bridge) has been removed.

In both cases, I believe no Phacility customers use these features anymore. I'm open to restoring them if they have significant customer use in the wild, but the complexity of the work required to maintain them across this change appears significant and I believe they see almost no modern use.

Major Changes

  • arc land X now means "land X and all ancestors of X".
    • If you stack changes in feature1, feature2, etc., branches, arc land featureN now lands all of the changes.
    • If you stack changes in a single X branch, arc land X now lands all of the changes in the stack.
    • You can also pass multiple refs explicitly: arc land X Y Z.
    • To land only X, Y, and Z, use --pick.
  • By default, all changes in a single land operation are pushed at once, and the entire operation (more or less) either succeeds or fails atomically. The new --incremental flag allows you to push and rebase changes individually instead, and may make it easier to land complex sequences of changes that require some user interaction (like merge conflict resolution) during some of the steps.

Minor Changes

  • arc land now functions when the remote is empty (usually, when you are landing the first change in a new repository).
  • The --delete-remote flag, which deleted remote bookmarks in Mercurial, has been removed. Future workflows (arc save and arc load) will provide tools for "saving changes". I wasn't able to find evidence that this flag sees any use. I'm open to revisiting this behavior if it does see use.
  • The --keep-branch flag is now named --keep-branches, to reflect that it may affect multiple branches.
  • The arc.land.onto.default configuration key is now named arc.land.onto. Because --onto now accepts multiple arguments, this key now accepts a list of values.
  • The arc.autostash configuration option is no longer respected by arc land. This has been replaced with configurable defaults for prompts. (Answer y* when prompted to indicate "always answer y to this prompt in the future".)
  • arc land will now retry if it loses a race to push the remote.
  • arc land now performs fewer working copy and remote operations, and may execute faster in large repositories.
  • arc land now performs more branch and history scanning operations, and may execute slower in large repositories.
  • After a change lands with a "squash" strategy, all local branches descending from that change are rebased onto the landed version of the change. For example, if you arc land feature1, your local feature2 branch will be automatically rebased.
  • arc land no longer automatically runs arc close-revision after landing a change. In the overwhelming majority of cases (when the repository is known to Phabricator) arc close-revision previously exited with no effect and this change has no impact on behavior (that is: for almost all users, your revision will still close automatically after you arc land, because arc land was not closing your revision in the first place). In other cases, revisions can generally be automatically closed by tracking the repository they land into in Diffusion.
  • arc land now requires a version of Phabricator which supports harbormaster.buildable.search and related API methods (introduced circa November 2018) to warn about ongoing or failed builds.

Changes to --onto

arc land may now land a change onto multiple target branches in the remote. You can select this behavior by passing --onto multiple times. For example:

$ arc land xyz --onto master --onto release-2.3

This will merge change xyz, then push it onto master and release-2.3 in the remote.

Note that each change passed to arc land is merged exactly once, so these two commands are not equivalent:

Merge Once, Push to Two Branches
$ arc land xyz --onto master --onto release-2.3
Merge Twice
$ arc land xyz --onto master --keep-branch
$ arc land xyz --onto release-2.3

In the first case, master and release-2.3 are guaranteed to be in exactly the same state after arc land exits. In the second case, xyz is merged into two different states and the resulting states of master and release-2.3 may differ.

The arc.land.onto configuration option now has higher precedence than following Git upstreams. For example, if arc.land.onto is configured as master, but your local branch feature1 tracks origin/alice-feature1, your change will now land onto master, not alice-feature1. In all cases, you can explicitly select a branch to land onto with --onto, which has the highest precedence.

New Concept: --into

arc land may now merge changes into a state other than the state of the ref or refs it is pushing to. In general, this:

$ arc land xyz --into A --onto B

...means:

  • merge change xyz into A to create state xyz1; then
  • push xyz1 to B; then
  • delete xyz if it's a branch.

Usually, you want --into and --onto to be the same when you run arc land, and the value of --into will default to the value of --onto if you do not specify a different value explicitly. For example, these commands are broadly equivalent:

Broadly Equivalent: Into defaults to Onto
$ arc land xyz --into Q --onto Q
$ arc land xyz --onto Q

(These commands have different behavior if ref Q does not exist; the former invocation is an error.)

In almost all cases, you can ignore these new flags and let arc select the default behaviors. However, in special situations, you may want to control the merge behavior in greater detail by using --into (or the related flags, --into-remote <remote>, --into-local, and --into-empty). For example, this command:

$ arc land xyz --into-remote upstream --into master --onto-remote internal --onto release-1.2.9x

...means:

  • fetch upstream/master;
  • merge state xyz into it, creating state xyz1;
  • push state xyz1 to internal/release-1.2.9x;
  • delete xyz if it's a branch.

These new flags allow specification of "into" behavior in more detail:

  • --into-remote <remote>: read the "into" ref from a remote other than the "onto" remote.
  • --into-local: use the local state of the "into" ref instead of fetching it from a remote.
  • --into-empty: use the empty state as the "into" state. Normally, this is selected automatically when you run arc land for the first time in a new repository.

Event Timeline

epriestley triaged this task as Normal priority.Jun 2 2020, 7:10 PM
epriestley created this task.