Update Aug. 2021, 10 years later: no more "recursive merge":
With Git 2.34 (Q4 2021), the default merge strategy becomes ORT ("Ostensibly Recursive's Twin")
See commit 81483fe, commit 67feccd, commit 6320813, commit b36ade2, commit 4d15c85, commit 002a6df, commit 510415e, commit e80178e, commit b378df7, commit e037c2e (04 Aug 2021) by Elijah Newren (newren
).
(Merged by Junio C Hamano -- gitster
-- in commit aca13c2, 30 Aug 2021)
81483fe613
:Update error message and code comment
Acked-by: Derrick Stolee
Acked-by: Johannes Schindelin
Signed-off-by: Elijah Newren
There were two locations in the code that referred to 'merge-recursive' but which were also applicable to 'merge-ort'.
Update them to more general wording.
With Git 2.34 (Q4 2021), documentation updates.
See commit 81483fe, commit 67feccd, commit 6320813, commit b36ade2, commit 4d15c85, commit 002a6df, commit 510415e, commit e80178e, commit b378df7, commit e037c2e (04 Aug 2021) by Elijah Newren (newren
).
(Merged by Junio C Hamano -- gitster
-- in commit aca13c2, 30 Aug 2021)
merge-strategies
now includes in its man page:
ort
This is meant as a drop-in replacement for the recursive
algorithm (as reflected in its acronym -- "Ostensibly
Recursive's Twin"), and will likely replace it in the future.
It fixes corner cases that the recursive
strategy handles
suboptimally, and is significantly faster in large
repositories -- especially when many renames are involved.
The ort
strategy takes all the same options as recursive
.
However, it ignores three of those options: no-renames
,
patience
and diff-algorithm
.
It always runs with rename
detection (it handles it much faster than recursive
does), and
it specifically uses diff-algorithm=histogram
.
And:
With Git 2.34 (Q4 2021), use ort
instead of recursive
as the default merge strategy.
See commit f5a3c5e, commit 6a5fb96 (04 Aug 2021) by Elijah Newren (newren
).
(Merged by Junio C Hamano -- gitster
-- in commit 8778fa8, 30 Aug 2021)
f5a3c5e637
:Update docs for change of default merge backend
Signed-off-by: Elijah Newren
Make it clear that ort
is the default merge strategy now rather than recursive
, including moving ort
to the front of the list of merge strategies.
git rebase
now includes in its man page:
specified, -s ort
. Note the reversal of 'ours' and
git rebase
now includes in its man page:
By default, the merge
command will use the ort
merge strategy for
regular merges, and octopus
for octopus merges.
One can specify a
default strategy for all merges using the --strategy
argument when
invoking rebase, or can override specific merges in the interactive
list of commands by using an exec
command to call git merge
explicitly with a --strategy
argument.
Note that when calling git merge
explicitly like this, you can make use of the fact that the
labels are worktree-local refs (the ref refs/rewritten/onto
would
correspond to the label onto
, for example) in order to refer to the
branches you want to merge.
gitfaq
now includes in its man page:
By default, when Git does a merge, it uses a strategy called the ort
merge-strategies
now includes in its man page:
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
.
merge-strategies
now includes in its man page:
The 'ort' strategy can take the following options:
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. This was
the default strategy for resolving two heads from Git v0.99.9k
until v2.33.0.
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 synonym for diff-algorithm=patience
.
no-renames;;
Turn off rename detection. This overrides the merge.renames
configuration variable.
Original answer (2011)
I see here the patch introducing the patience option to the recursive merge strategy, base on Git1.7.2.2, but I don't see it in any of the subsequent release notes.
Yet the patience diff algorithm has been presented since 2009, and is detailed here.
> grep -i patience *.c
diff.c: else if (!strcmp(arg, "--patience"))
diff.c: DIFF_XDL_SET(options, PATIENCE_DIFF);
merge-recursive.c: else if (!strcmp(s, "patience"))
merge-recursive.c: o->xdl_opts |= XDF_PATIENCE_DIFF;
The merge command should understand this option... but this function below seems to never be called (not anywhere in merge-recursive.c
or in any other *.c
file!):
int parse_merge_opt(struct merge_options *o, const char *s)
{
if (!s || !*s)
return -1;
if (!strcmp(s, "ours"))
o->recursive_variant = MERGE_RECURSIVE_OURS;
else if (!strcmp(s, "theirs"))
o->recursive_variant = MERGE_RECURSIVE_THEIRS;
else if (!strcmp(s, "subtree"))
o->subtree_shift = "";
else if (!prefixcmp(s, "subtree="))
o->subtree_shift = s + strlen("subtree=");
else if (!strcmp(s, "patience"))
o->xdl_opts |= XDF_PATIENCE_DIFF;
else if (!strcmp(s, "ignore-space-change"))
o->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE;
else if (!strcmp(s, "ignore-all-space"))
o->xdl_opts |= XDF_IGNORE_WHITESPACE;
else if (!strcmp(s, "ignore-space-at-eol"))
o->xdl_opts |= XDF_IGNORE_WHITESPACE_AT_EOL;
else if (!strcmp(s, "renormalize"))
o->renormalize = 1;
else if (!strcmp(s, "no-renormalize"))
o->renormalize = 0;
else if (!prefixcmp(s, "rename-threshold=")) {
const char *score = s + strlen("rename-threshold=");
if ((o->rename_score = parse_rename_score(&score)) == -1 || *score != 0)
return -1;
}
else
return -1;
return 0;
}
The "Unknown option" error message is only printed by the handle_options
function in git.c
.
And XDF_PATIENCE_DIFF
doesn't show anywhere else in git sources (1.7.4)... so yes, I don't know how this could be implemented for the merge.