]> git.ipfire.org Git - thirdparty/git.git/commitdiff
merge: do not abort early if one strategy fails to handle the merge
authorElijah Newren <newren@gmail.com>
Sat, 23 Jul 2022 01:53:14 +0000 (01:53 +0000)
committerJunio C Hamano <gitster@pobox.com>
Sat, 23 Jul 2022 04:45:23 +0000 (21:45 -0700)
builtin/merge is setup to allow multiple strategies to be specified,
and it will find the "best" result and use it.  This is defeated if
some of the merge strategies abort early when they cannot handle the
merge.  Fix the logic that calls recursive and ort to not do such an
early abort, but instead return "2" or "unhandled" so that the next
strategy can try to handle the merge.

Coming up with a testcase for this is somewhat difficult, since
recursive and ort both handle nearly any two-headed merge (there is
a separate code path that checks for non-two-headed merges and
already returns "2" for them).  So use a somewhat synthetic testcase
of having the index not match HEAD before the merge starts, since all
merge strategies will abort for that.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/merge.c
t/t6402-merge-rename.sh
t/t6424-merge-unrelated-index-changes.sh
t/t6439-merge-co-error-msgs.sh

index b43876f68e44262bb7eab6c5cd8f3e5e937ef964..c120ad619c478a27e7911981509f30f5225ff6de 100644 (file)
@@ -754,8 +754,10 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
                else
                        clean = merge_recursive(&o, head, remoteheads->item,
                                                reversed, &result);
-               if (clean < 0)
-                       exit(128);
+               if (clean < 0) {
+                       rollback_lock_file(&lock);
+                       return 2;
+               }
                if (write_locked_index(&the_index, &lock,
                                       COMMIT_LOCK | SKIP_IF_UNCHANGED))
                        die(_("unable to write %s"), get_index_file());
index 3a32b1a45cf8e4bf2a7b42eeec98923262b3e470..772238e582c6f11b81c12a519f81bbe48cecf635 100755 (executable)
@@ -210,7 +210,7 @@ test_expect_success 'updated working tree file should prevent the merge' '
        echo >>M one line addition &&
        cat M >M.saved &&
        git update-index M &&
-       test_expect_code 128 git pull --no-rebase . yellow &&
+       test_expect_code 2 git pull --no-rebase . yellow &&
        test_cmp M M.saved &&
        rm -f M.saved
 '
index 187c761ad84f04f51b5b7026505956cd96e2c04e..615061c7af442bceafc302f2027b543828ac3e0c 100755 (executable)
@@ -275,4 +275,20 @@ test_expect_success 'subtree' '
        test_path_is_missing .git/MERGE_HEAD
 '
 
+test_expect_success 'with multiple strategies, recursive or ort failure do not early abort' '
+       git reset --hard &&
+       git checkout B^0 &&
+
+       test_seq 0 10 >a &&
+       git add a &&
+
+       sane_unset GIT_TEST_MERGE_ALGORITHM &&
+       test_must_fail git merge -s recursive -s ort -s octopus C^0 >output 2>&1 &&
+
+       grep "Trying merge strategy recursive..." output &&
+       grep "Trying merge strategy ort..." output &&
+       grep "Trying merge strategy octopus..." output &&
+       grep "No merge strategy handled the merge." output
+'
+
 test_done
index 5bfb027099a6d22849739075de82f3c0af7ca513..52cf0c87690be83e758b97c12b0ab00fa77613a2 100755 (executable)
@@ -47,6 +47,7 @@ test_expect_success 'untracked files overwritten by merge (fast and non-fast for
                export GIT_MERGE_VERBOSITY &&
                test_must_fail git merge branch 2>out2
        ) &&
+       echo "Merge with strategy ${GIT_TEST_MERGE_ALGORITHM:-ort} failed." >>expect &&
        test_cmp out2 expect &&
        git reset --hard HEAD^
 '