Skip to content

Commit

Permalink
merge-recursive --patience
Browse files Browse the repository at this point in the history
Teach the merge-recursive strategy a --patience option to use the
"patience diff" algorithm, which tends to improve results when
cherry-picking a patch that reorders functions at the same time as
refactoring them.

To support this, struct merge_options and ll_merge_options gain an
xdl_opts member, so programs can use arbitrary xdiff flags (think
"XDF_IGNORE_WHITESPACE") in a git-aware merge.

git merge and git rebase can be passed the -Xpatience option to
use this.

[jn: split from --ignore-space patch; with documentation]

Signed-off-by: Justin Frankel <justin@cockos.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
justinfrankel authored and gitster committed Aug 26, 2010
1 parent 712516b commit 58a1ece
Show file tree
Hide file tree
Showing 6 changed files with 14 additions and 0 deletions.
7 changes: 7 additions & 0 deletions Documentation/merge-strategies.txt
Expand Up @@ -40,6 +40,13 @@ the other tree did, declaring 'our' history contains all that happened in it.
theirs;;
This is opposite of 'ours'.

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

renormalize;;
This runs a virtual check-out and check-in of all three stages
of a file when resolving a three-way merge. This option is
Expand Down
1 change: 1 addition & 0 deletions builtin/merge-recursive.c
Expand Up @@ -2,6 +2,7 @@
#include "commit.h"
#include "tag.h"
#include "merge-recursive.h"
#include "xdiff-interface.h"

static const char *better_branch_name(const char *branch)
{
Expand Down
1 change: 1 addition & 0 deletions ll-merge.c
Expand Up @@ -86,6 +86,7 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
memset(&xmp, 0, sizeof(xmp));
xmp.level = XDL_MERGE_ZEALOUS;
xmp.favor = opts->variant;
xmp.xpp.flags = opts->xdl_opts;
if (git_xmerge_style >= 0)
xmp.style = git_xmerge_style;
if (marker_size > 0)
Expand Down
1 change: 1 addition & 0 deletions ll-merge.h
Expand Up @@ -9,6 +9,7 @@ struct ll_merge_options {
unsigned virtual_ancestor : 1;
unsigned variant : 2; /* favor ours, favor theirs, or union merge */
unsigned renormalize : 1;
long xdl_opts;
};

int ll_merge(mmbuffer_t *result_buf,
Expand Down
3 changes: 3 additions & 0 deletions merge-recursive.c
Expand Up @@ -613,6 +613,7 @@ static int merge_3way(struct merge_options *o,
int merge_status;

ll_opts.renormalize = o->renormalize;
ll_opts.xdl_opts = o->xdl_opts;

if (o->call_depth) {
ll_opts.virtual_ancestor = 1;
Expand Down Expand Up @@ -1512,6 +1513,8 @@ int parse_merge_opt(struct merge_options *o, const char *s)
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, "renormalize"))
o->renormalize = 1;
else if (!strcmp(s, "no-renormalize"))
Expand Down
1 change: 1 addition & 0 deletions merge-recursive.h
Expand Up @@ -15,6 +15,7 @@ struct merge_options {
const char *subtree_shift;
unsigned buffer_output : 1;
unsigned renormalize : 1;
long xdl_opts;
int verbosity;
int diff_rename_limit;
int merge_rename_limit;
Expand Down

0 comments on commit 58a1ece

Please sign in to comment.