**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:
| VCS | `history.immutable` | Old Default Strategy | New Default Strategy |
|---|---|---|---|
| Git | <Not Configured> | squash | squash |
| Git | false | squash | squash |
| Git | true | !!merge!! | !!squash!! |
| Mercurial | <Not Configured> | //N/A// | squash |
| Mercurial | false | squash | squash |
| Mercurial | true | //N/A// | squash |
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 Flag | New 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 it 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:
```name="Merge Once, Push to Two Branches"
$ arc land xyz --onto master --onto release-2.3
```
```name="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:
```name="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.