Skip to content

Commit

Permalink
Update docs for change of default merge backend
Browse files Browse the repository at this point in the history
Make multiple documentation updates to bring things up to date as we
change the default merge backend...

Add a section for `ort` within merge-strategies.txt; while it accepts
the same flags as `recursive` (even if it ignores three of them) and is
meant as a drop in replacement, it still makes sense to explicitly cover
it.

Change several locations in the docs that referred to `recursive` as the
default merge backend, and fix a few that said or implied that only
`recursive` had certain abilities (such as rename detection).

Fix up some wording in directory-rename-detection.txt due to some
restructurings performed while optimizing both the ort backend and the
rename detection machinery.

Drop the "is considered generally safe and fast" from the description of
the `resolve` strategy, since that implies the other strategies are not.
While such an implication may have been true in 2005 when written, it
may well be that `ort` is faster today (since it does not need to
recurse into all directories).  Also, since `resolve` was the default
for less than a year while `recursive` has been the default for a decade
and a half, I think `recursive` is more battle-tested than `resolve` is.
Move the description of `resolve` near `octopus` and `ours` while at it
since it is no longer the default merge algorithm and hasn't been for a
very long time.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
  • Loading branch information
newren authored and derrickstolee committed Aug 2, 2021
1 parent a855348 commit 66b7094
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 59 deletions.
17 changes: 9 additions & 8 deletions Documentation/git-rebase.txt
Original file line number Diff line number Diff line change
Expand Up @@ -340,9 +340,10 @@ See also INCOMPATIBLE OPTIONS below.

-m::
--merge::
Use merging strategies to rebase. When the recursive (default) merge
strategy is used, this allows rebase to be aware of renames on the
upstream side. This is the default.
Use merging strategies to rebase. When either the `ort`
(default) or `recursive` merge strategy is used, this allows
rebase to be aware of renames on the upstream side. This is the
default.
+
Note that a rebase merge works by replaying each commit from the working
branch on top of the <upstream> branch. Because of this, when a merge
Expand All @@ -355,8 +356,8 @@ See also INCOMPATIBLE OPTIONS below.
-s <strategy>::
--strategy=<strategy>::
Use the given merge strategy.
If there is no `-s` option 'git merge-recursive' is used
instead. This implies --merge.
If there is no `-s` option the `ort` strategy is the default.
This implies --merge.
+
Because 'git rebase' replays each commit from the working branch
on top of the <upstream> branch using the given strategy, using
Expand All @@ -369,7 +370,7 @@ See also INCOMPATIBLE OPTIONS below.
--strategy-option=<strategy-option>::
Pass the <strategy-option> through to the merge strategy.
This implies `--merge` and, if no strategy has been
specified, `-s recursive`. Note the reversal of 'ours' and
specified, `-s ort`. Note the reversal of 'ours' and
'theirs' as noted above for the `-m` option.
+
See also INCOMPATIBLE OPTIONS below.
Expand Down Expand Up @@ -530,7 +531,7 @@ The `--rebase-merges` mode is similar in spirit to the deprecated
where commits can be reordered, inserted and dropped at will.
+
It is currently only possible to recreate the merge commits using the
`recursive` merge strategy; Different merge strategies can be used only via
`ort` merge strategy; different merge strategies can be used only via
explicit `exec git merge -s <strategy> [...]` commands.
+
See also REBASING MERGES and INCOMPATIBLE OPTIONS below.
Expand Down Expand Up @@ -1219,7 +1220,7 @@ successful merge so that the user can edit the message.
If a `merge` command fails for any reason other than merge conflicts (i.e.
when the merge operation did not even start), it is rescheduled immediately.

At this time, the `merge` command will *always* use the `recursive`
At this time, the `merge` command will *always* use the `ort`
merge strategy for regular merges, and `octopus` for octopus merges,
with no way to choose a different one. To work around
this, an `exec` command can be used to call `git merge` explicitly,
Expand Down
2 changes: 1 addition & 1 deletion Documentation/gitfaq.txt
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ best to always use a regular merge commit.

[[merge-two-revert-one]]
If I make a change on two branches but revert it on one, why does the merge of those branches include the change?::
By default, when Git does a merge, it uses a strategy called the recursive
By default, when Git does a merge, it uses a strategy called the ort
strategy, which does a fancy three-way merge. In such a case, when Git
performs the merge, it considers exactly three points: the two heads and a
third point, called the _merge base_, which is usually the common ancestor of
Expand Down
4 changes: 2 additions & 2 deletions Documentation/merge-options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ With --squash, --commit is not allowed, and will fail.
Use the given merge strategy; can be supplied more than
once to specify them in the order they should be tried.
If there is no `-s` option, a built-in list of strategies
is used instead ('git merge-recursive' when merging a single
head, 'git merge-octopus' otherwise).
is used instead (`ort` when merging a single head,
`octopus` otherwise).

-X <option>::
--strategy-option=<option>::
Expand Down
98 changes: 57 additions & 41 deletions Documentation/merge-strategies.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,23 @@ backend 'merge strategies' to be chosen with `-s` option. Some strategies
can also take their own options, which can be passed by giving `-X<option>`
arguments to `git merge` and/or `git pull`.

resolve::
This can only resolve two heads (i.e. the current branch
and another branch you pulled from) using a 3-way merge
algorithm. It tries to carefully detect criss-cross
merge ambiguities and is considered generally safe and
fast.

recursive::
This can only resolve two heads using a 3-way merge
algorithm. When there is more than one common
ancestor that can be used for 3-way merge, it creates a
merged tree of the common ancestors and uses that as
the reference tree for the 3-way merge. This has been
reported to result in fewer merge conflicts without
causing mismerges by tests done on actual merge commits
taken from Linux 2.6 kernel development history.
Additionally this can detect and handle merges involving
renames, but currently cannot make use of detected
copies. This is the default merge strategy when pulling
or merging one branch.
ort::
This is the default merge strategy when pulling or merging one
branch. This strategy can only resolve two heads using a
3-way merge algorithm. When there is more than one common
ancestor that can be used for 3-way merge, it creates a merged
tree of the common ancestors and uses that as the reference
tree for the 3-way merge. This has been reported to result in
fewer merge conflicts without causing mismerges by tests done
on actual merge commits taken from Linux 2.6 kernel
development history. Additionally this strategy can detect
and handle merges involving renames. It does not make use of
detected copies. The name for this algorithm is an acronym
("Ostensibly Recursive's Twin") and came from the fact that it
was written as a replacement for the previous default
algorithm, recursive.
+
The 'recursive' strategy can take the following options:
The 'ort' strategy can take the following options:

ours;;
This option forces conflicting hunks to be auto-resolved cleanly by
Expand All @@ -43,19 +38,6 @@ theirs;;
This is the opposite of 'ours'; note that, unlike 'ours', there is
no 'theirs' merge strategy to confuse this merge option with.

patience;;
With this option, 'merge-recursive' spends a little extra time
to avoid mismerges that sometimes occur due to unimportant
matching lines (e.g., braces from distinct functions). Use
this when the branches to be merged have diverged wildly.
See also linkgit:git-diff[1] `--patience`.

diff-algorithm=[patience|minimal|histogram|myers];;
Tells 'merge-recursive' to use a different diff algorithm, which
can help avoid mismerges that occur due to unimportant matching
lines (such as braces from distinct functions). See also
linkgit:git-diff[1] `--diff-algorithm`.

ignore-space-change;;
ignore-all-space;;
ignore-space-at-eol;;
Expand Down Expand Up @@ -84,11 +66,6 @@ no-renormalize;;
Disables the `renormalize` option. This overrides the
`merge.renormalize` configuration variable.

no-renames;;
Turn off rename detection. This overrides the `merge.renames`
configuration variable.
See also linkgit:git-diff[1] `--no-renames`.

find-renames[=<n>];;
Turn on rename detection, optionally setting the similarity
threshold. This is the default. This overrides the
Expand All @@ -105,6 +82,45 @@ subtree[=<path>];;
is prefixed (or stripped from the beginning) to make the shape of
two trees to match.

recursive::
This can only resolve two heads using a 3-way merge
algorithm. When there is more than one common
ancestor that can be used for 3-way merge, it creates a
merged tree of the common ancestors and uses that as
the reference tree for the 3-way merge. This has been
reported to result in fewer merge conflicts without
causing mismerges by tests done on actual merge commits
taken from Linux 2.6 kernel development history.
Additionally this can detect and handle merges involving
renames. It does not make use of detected copies.
+
The 'recursive' strategy takes the same options as 'ort'. However,
there are three additional options that 'ort' ignores (not documented
above) that are potentially useful with the 'recursive' strategy:

patience;;
Deprecated shorthand for diff-algorithm=patience.

diff-algorithm=[patience|minimal|histogram|myers];;
Use a different diff algorithm while merging, which can help
avoid mismerges that occur due to unimportant matching lines
(such as braces from distinct functions). See also
linkgit:git-diff[1] `--diff-algorithm`. Note that `ort`
specifically uses diff-algorithm=histogram, while `recursive`
defaults to the `diff.algorithm` config setting.

no-renames;;
Turn off rename detection, which can be computationally much
more expensive for the `recursive` strategy than for `ort`.
This overrides the `merge.renames` configuration variable. See
also linkgit:git-diff[1] `--no-renames`.

resolve::
This can only resolve two heads (i.e. the current branch
and another branch you pulled from) using a 3-way merge
algorithm. It tries to carefully detect criss-cross
merge ambiguities. It cannot handle renames.

octopus::
This resolves cases with more than two heads, but refuses to do
a complex merge that needs manual resolution. It is
Expand All @@ -121,13 +137,13 @@ ours::
the 'recursive' merge strategy.

subtree::
This is a modified recursive strategy. When merging trees A and
This is a modified ort strategy. When merging trees A and
B, if B corresponds to a subtree of A, B is first adjusted to
match the tree structure of A, instead of reading the trees at
the same level. This adjustment is also done to the common
ancestor tree.

With the strategies that use 3-way merge (including the default, 'recursive'),
With the strategies that use 3-way merge (including the default, 'ort'),
if a change is made on both branches, but later reverted on one of the
branches, that change will be present in the merged result; some people find
this behavior confusing. It occurs because only the heads and the merge base
Expand Down
14 changes: 8 additions & 6 deletions Documentation/technical/directory-rename-detection.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ Directory rename detection
==========================

Rename detection logic in diffcore-rename that checks for renames of
individual files is aggregated and analyzed in merge-recursive for cases
where combinations of renames indicate that a full directory has been
renamed.
individual files is also aggregated there and then analyzed in either
merge-ort or merge-recursive for cases where combinations of renames
indicate that a full directory has been renamed.

Scope of abilities
------------------
Expand Down Expand Up @@ -88,9 +88,11 @@ directory rename detection support in:
Folks have requested in the past that `git diff` detect directory
renames and somehow simplify its output. It is not clear whether this
would be desirable or how the output should be simplified, so this was
simply not implemented. Further, to implement this, directory rename
detection logic would need to move from merge-recursive to
diffcore-rename.
simply not implemented. Also, while diffcore-rename has most of the
logic for detecting directory renames, some of the logic is still found
within merge-ort and merge-recursive. Fully supporting directory
rename detection in diffs would require copying or moving the remaining
bits of logic to the diff machinery.

* am

Expand Down
2 changes: 1 addition & 1 deletion Documentation/user-manual.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3190,7 +3190,7 @@ that *updated* thing--the old state that you added originally ends up
not being pointed to by any commit or tree, so it's now a dangling blob
object.

Similarly, when the "recursive" merge strategy runs, and finds that
Similarly, when the "ort" merge strategy runs, and finds that
there are criss-cross merges and thus more than one merge base (which is
fairly unusual, but it does happen), it will generate one temporary
midway tree (or possibly even more, if you had lots of criss-crossing
Expand Down

0 comments on commit 66b7094

Please sign in to comment.