summaryrefslogtreecommitdiff
path: root/src/merge.c
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2018-01-21 18:05:45 +0000
committerEdward Thomson <ethomson@edwardthomson.com>2018-02-04 10:29:41 +0000
commitb924df1eadfaf33285d8020c50cb18ddde1a8165 (patch)
treec2cfdd31adb8c2831d159817cff9a23e74561ab4 /src/merge.c
parented51feb74b33ca115ddf739ce3574a76cb7a6fa6 (diff)
downloadlibgit2-b924df1eadfaf33285d8020c50cb18ddde1a8165.tar.gz
merge: reverse merge bases for recursive merge
When the commits being merged have multiple merge bases, reverse the order when creating the virtual merge base. This is for compatibility with git's merge-recursive algorithm, and ensures that we build identical trees. Git does this to try to use older merge bases first. Per 8918b0c: > It seems to be the only sane way to do it: when a two-head merge is > done, and the merge-base and one of the two branches agree, the > merge assumes that the other branch has something new. > > If we start creating virtual commits from newer merge-bases, and go > back to older merge-bases, and then merge with newer commits again, > chances are that a patch is lost, _because_ the merge-base and the > head agree on it. Unlikely, yes, but it happened to me.
Diffstat (limited to 'src/merge.c')
-rw-r--r--src/merge.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/src/merge.c b/src/merge.c
index aae5d764a..37c83eccd 100644
--- a/src/merge.c
+++ b/src/merge.c
@@ -2263,7 +2263,7 @@ static int compute_base(
git_oidarray bases = {0};
git_annotated_commit *base = NULL, *other = NULL, *new_base = NULL;
git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
- size_t i;
+ size_t i, base_count;
int error;
*out = NULL;
@@ -2272,16 +2272,20 @@ static int compute_base(
memcpy(&opts, given_opts, sizeof(git_merge_options));
if ((error = insert_head_ids(&head_ids, one)) < 0 ||
- (error = insert_head_ids(&head_ids, two)) < 0)
+ (error = insert_head_ids(&head_ids, two)) < 0 ||
+ (error = git_merge_bases_many(&bases, repo,
+ head_ids.size, head_ids.ptr)) < 0)
goto done;
- if ((error = git_merge_bases_many(&bases, repo,
- head_ids.size, head_ids.ptr)) < 0 ||
- (error = git_annotated_commit_lookup(&base, repo, &bases.ids[0])) < 0 ||
- (opts.flags & GIT_MERGE_NO_RECURSIVE))
+ base_count = (opts.flags & GIT_MERGE_NO_RECURSIVE) ? 0 : bases.count;
+
+ if (base_count)
+ git_oidarray__reverse(&bases);
+
+ if ((error = git_annotated_commit_lookup(&base, repo, &bases.ids[0])) < 0)
goto done;
- for (i = 1; i < bases.count; i++) {
+ for (i = 1; i < base_count; i++) {
recursion_level++;
if (opts.recursion_limit && recursion_level > opts.recursion_limit)