How to merge a branch with git using patience option provided by the recursive strategy? I'm using git version 1.7.3.1.msysgit.0
Even docs are not consistent and, what's more, differ from what the actual command outputs.
Docs say:
git merge [-s
<strategy>] [-X<strategy-option>]<commit>
and further in text:
-X
<option>
(no space)
Output from the command says:
-X, --strategy-option <option=value> option for selected merge strategy So I tried a couple versions with following results:
$ git merge -s recursive -Xpatience sourceBranch fatal: Unknown option for merge-recursive: -Xpatience $ git merge -X patience sourceBranch fatal: Unknown option for merge-recursive: -Xpatience $ git merge -Xpatience sourceBranch fatal: Unknown option for merge-recursive: -Xpatience $ git merge --strategy-option patience sourceBranch fatal: Unknown option for merge-recursive: -Xpatience $ git merge -X option=patience sourceBranch fatal: Unknown option for merge-recursive: -Xoption=patience $ git merge --strategy-option option=patience sourceBranch fatal: Unknown option for merge-recursive: -Xoption=patience $ git merge option=patience sourceBranch fatal: 'option=patience' does not point to a commit $ git merge -X option=patience sourceBranch fatal: Unknown option for merge-recursive: -Xoption=patience It looks as if the option's not implemented...
You can use git merge-base --all to see the merge base candidate commits. Using -s resolve will pick one of them, while -s recursive will take all of them, merge them into a new commit, and use that new commit as the merge base.
Recursive is the default merge strategy when pulling or merging one branch. 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.
The most commonly used strategies are Fast Forward Merge and Recursive Merge. In this most commonly used merge strategy, history is just one straight line. When you create a branch, make some commits in that branch, the time you're ready to merge, there is no new merge on the master.
The --patience option for git merge-recursive was introduced in commit 58a1ece478c6038a7eb0b6e494d563bd5e6d5978. You can find out in a clone of git.git what versions contain this change with git tag --contains 58a1ece478:
v1.7.4 v1.7.4-rc0 v1.7.4-rc1 v1.7.4-rc2 v1.7.4-rc3 v1.7.4.1 So I suspect that you're just using a slightly too old version of mSysGit. There is a preview version of 1.7.4 available now - I think you should try that one.
I've just tried this with git version 1.7.4, and the following command line syntax works for me:
git merge -s recursive -X patience other-branch
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 commentAcked-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:
ortThis is meant as a drop-in replacement for the
recursivealgorithm (as reflected in its acronym -- "Ostensibly Recursive's Twin"), and will likely replace it in the future.It fixes corner cases that the
recursivestrategy handles suboptimally, and is significantly faster in large repositories -- especially when many renames are involved.The
ortstrategy takes all the same options asrecursive.
However, it ignores three of those options:no-renames,patienceanddiff-algorithm.
It always runs with rename detection (it handles it much faster thanrecursivedoes), and it specifically usesdiff-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 backendSigned-off-by: Elijah Newren
Make it clear that
ortis the default merge strategy now rather thanrecursive, including movingortto 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
mergecommand will use theortmerge strategy for regular merges, andoctopusfor octopus merges.
One can specify a default strategy for all merges using the--strategyargument when invoking rebase, or can override specific merges in the interactive list of commands by using anexeccommand to callgit mergeexplicitly with a--strategyargument.
Note that when callinggit mergeexplicitly like this, you can make use of the fact that the labels are worktree-local refs (the refrefs/rewritten/ontowould correspond to the labelonto, 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:
ortThis 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:
recursiveThis 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.renamesconfiguration 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With