On Wed, May 11, 2022 at 4:21 AM ZheNing Hu <adlternative@xxxxxxxxx> wrote: > > Elijah Newren <newren@xxxxxxxxx> 于2022年5月10日周二 15:07写道: > > > > On Sun, May 8, 2022 at 7:44 AM ZheNing Hu <adlternative@xxxxxxxxx> wrote: [...] > > > Thanks for clarifying. As I reply to Christian, when I just use "git > > > merge A B C" happily, > > > and there is a conflict, so I try "git merge --abort" as usual, but it > > > can not work... git tell me: > > > > > > fatal: There is no merge to abort (MERGE_HEAD missing). > > > > Sounds like a bug to me; .git/MERGE_HEAD should be written. That file > > is created for me when I set up a simple octopus merge that has > > conflicts. Do you have a set of steps others can use to reproduce the > > problem you are seeing? > > Let me minimally reproduce this question (with git 2.33.0): > > #!/bin/bash > > rm -rf test-repo > git init test-repo > cd test-repo > git branch -m main > echo base > base > git add . > git commit -m "base" > git branch -c dev-1 > git branch -c dev-2 > echo main > main > git add . > git commit -m "main change" > git checkout dev-1 > echo dev-1 >> base > git add . > git commit -m "dev-1 change" > git checkout dev-2 > echo dev-2 >> base > git add . > git commit -m "dev-2 change" > git checkout main > echo main >> base > git add . > git commit -m "main change" > git merge dev-1 dev-2 > file .git/MERGE_HEAD > > which output: > > .git/MERGE_HEAD: cannot open `.git/MERGE_HEAD' (No such file or directory) Ah, thanks. With this testcase, the output is: $ git merge dev-1 dev-2 Trying simple merge with dev-1 Simple merge did not work, trying automatic merge. Auto-merging base ERROR: content conflict in base fatal: merge program failed Automated merge did not work. Should not be doing an octopus. Merge with strategy octopus failed. Also, if we check `git status`: $ git status On branch main Unmerged paths: (use "git restore --staged <file>..." to unstage) (use "git add <file>..." to mark resolution) both modified: base no changes added to commit (use "git add" and/or "git commit -a") And in git-merge-octopus.sh we see: case "$OCTOPUS_FAILURE" in 1) # We allow only last one to have a hand-resolvable # conflicts. Last round failed and we still had # a head to merge. gettextln "Automated merge did not work." gettextln "Should not be doing an octopus." exit 2 esac and in builtin/merge.c, we see: /* * The backend exits with 1 when conflicts are * left to be resolved, with 2 when it does not * handle the given merge at all. */ Which means git-merge-octopus.sh is claiming it can't handle this type of merge, and some other merge strategy should be tried, and implicitly that it didn't leave any conflicts to be resolved because it can't handle this merge. But it clearly decides to leave the modifications it made to the index and working tree around, which just seems wrong to me. If it doesn't handle the merge and other merge strategies (if available) should be tried, it should leave things the way it found them. So, perhaps a patch like the below would do that; can you give it a try to see if it solves your cases (it works for your simplified testcase, but I'm curious about your more involved cases and if it works for them too)? ----- >8 ----- diff --git a/git-merge-octopus.sh b/git-merge-octopus.sh index 7d19d37951..6ddbdc8f56 100755 --- a/git-merge-octopus.sh +++ b/git-merge-octopus.sh @@ -47,6 +47,13 @@ then git diff-index --cached --name-only HEAD -- | sed -e 's/^/ /' exit 2 fi + +# If octopus is inapplicable, make sure we undo any changes we made first +cannot_octopus() { + git reset --merge + exit 2 +} + MRC=$(git rev-parse --verify -q $head) MRT=$(git write-tree) NON_FF_MERGE=0 @@ -60,7 +67,7 @@ do # a head to merge. gettextln "Automated merge did not work." gettextln "Should not be doing an octopus." - exit 2 + cannot_octopus esac eval pretty_name=\${GITHEAD_$SHA1:-$SHA1} @@ -95,7 +102,8 @@ do NON_FF_MERGE=1 eval_gettextln "Trying simple merge with \$pretty_name" - git read-tree -u -m --aggressive $common $MRT $SHA1 || exit 2 + git read-tree -u -m --aggressive $common $MRT $SHA1 || cannot_octopus + next=$(git write-tree 2>/dev/null) if test $? -ne 0 then