diff --git a/builtin/merge.c b/builtin/merge.c index 3c4f415d87..f7c92c0e64 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -385,11 +385,11 @@ static void restore_state(const struct object_id *head, { struct strvec args = STRVEC_INIT; - if (is_null_oid(stash)) - return; - reset_hard(head, 1); + if (is_null_oid(stash)) + goto refresh_cache; + strvec_pushl(&args, "stash", "apply", "--index", "--quiet", NULL); strvec_push(&args, oid_to_hex(stash)); @@ -400,7 +400,9 @@ static void restore_state(const struct object_id *head, run_command_v_opt(args.v, RUN_GIT_CMD); strvec_clear(&args); - refresh_cache(REFRESH_QUIET); +refresh_cache: + if (discard_cache() < 0 || read_cache() < 0) + die(_("could not read index")); } /* This is called when no merge was necessary. */ diff --git a/t/t7607-merge-state.sh b/t/t7607-merge-state.sh new file mode 100755 index 0000000000..89a62ac53b --- /dev/null +++ b/t/t7607-merge-state.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +test_description="Test that merge state is as expected after failed merge" + +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +. ./test-lib.sh + +test_expect_success 'Ensure we restore original state if no merge strategy handles it' ' + test_commit --no-tag "Initial" base base && + + for b in branch1 branch2 branch3 + do + git checkout -b $b main && + test_commit --no-tag "Change on $b" base $b || return 1 + done && + + git checkout branch1 && + # This is a merge that octopus cannot handle. Note, that it does not + # just hit conflicts, it completely fails and says that it cannot + # handle this type of merge. + test_expect_code 2 git merge branch2 branch3 >output 2>&1 && + grep "fatal: merge program failed" output && + grep "Should not be doing an octopus" output && + + # Make sure we did not leave stray changes around when no appropriate + # merge strategy was found + git diff --exit-code --name-status && + test_path_is_missing .git/MERGE_HEAD +' + +test_done