Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git merge using recursive strategy and patience option

Tags:

git

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...

like image 940
Filip Zawada Avatar asked Feb 17 '11 02:02

Filip Zawada


People also ask

How do you solve merge by recursive strategy?

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.

What is git merge recursive strategy?

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.

What is the best git merge strategy?

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.


2 Answers

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 
like image 98
Mark Longair Avatar answered Sep 23 '22 11:09

Mark Longair


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.

like image 37
VonC Avatar answered Sep 19 '22 11:09

VonC