git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Question about pre-merge and git merge octopus strategy

From
Elijah Newren <newren@gmail.com>
Date
May 12, 2022, 15:04 UTC
Message-ID
<CABPp-BHmNBMypVDrE=gPMXoHT9uH-u4HJG1dAuY0tjSGrK0yPg@mail.gmail.com>
In-Reply-To
<CAOLTT8R7QmpvaFPTRs3xTpxr7eiuxF-ZWtvUUSC0-JOo9Y+SqA@mail.gmail.com>
On Wed, May 11, 2022 at 4:21 AM ZheNing Hu <adlternative@gmail.com> wrote:
>
> Elijah Newren <newren@gmail.com> 于2022年5月10日周二 15:07写道:
> >
> > On Sun, May 8, 2022 at 7:44 AM ZheNing Hu <adlternative@gmail.com> wrote:
[...]
Show 46 quoted lines
> > > 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
Previous: ZheNing HuNext: Junio C Hamano
Message 8 of 15 in “Question about pre-merge and git merge octopus strategy”
  1. ZheNing HuMay 6, 2022
  2. Christian CouderMay 6, 2022
  3. Elijah NewrenMay 7, 2022
  4. Junio C HamanoMay 7, 2022
  5. ZheNing HuMay 8, 2022
  6. Elijah NewrenMay 10, 2022
  7. ZheNing HuMay 11, 2022
  8. Elijah NewrenMay 12, 2022
  9. Junio C HamanoMay 12, 2022
  10. Elijah NewrenMay 13, 2022
  11. Junio C HamanoMay 13, 2022
  12. ZheNing HuMay 19, 2022
  13. Elijah NewrenMay 19, 2022
  14. ZheNing HuMay 8, 2022
  15. Carlo Marcelo Arenas BelónMay 8, 2022

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.