Home > Blockchain >  git rerere doesn't work on commit --amend?
git rerere doesn't work on commit --amend?

Time:11-26

I develop on a long-time feature branch recently, and there have master、stage branches. When I finish it on the feature branch. I need to merge that to the stage branch, because I want to package it for the staging environment and the stage branch contains specific contents for that. The first time I faced conflicts caused by maybe some other people merging too or just my feature branch being outdated, whatever resolve it normally, but after that when I merge some bug fixes on the feature branch to the stage branch again, the conflicts that I've fixed reappeared.

  1. I am curious why the git doesn't remember what I solved? or am I missing some mechanism of git?

After googling I find git rerere is feeding my requirement. but it looks like doesn't work on commit --amend after I resolved conflicts. It seems to require a commit, however, I'd like to collect related things to the one commit and push it at the last. 2. How to do that? rerere is really helpful.

At the end, I tried to merge the master branch to the feature branch wish to eliminate The conflicts every time when I merge the feature to the stage branch. but conflicts still exist, which makes me more curious about question one.

CodePudding user response:

To get what you're asking for, you can simply run git rerere yourself. But you should not do this.

Longer: why you shouldn't do this

The rerere code (which re-uses re-corded re-solutions to prior merge conflicts) applies when you create merge conflicts. You create merge conflicts by invoking Git's merge engine, typically by running git merge, but also by using git cherry-pick and git revert, including the cherry-picking steps involved in git rebase.

Note that git commit, with or without --amend, is not in the above list! Running git commit --amend simply commits the current index content with its parent(s) set to the parent(s) of the HEAD commit. I think you mostly understand this part already—but consider that, when you run git merge and have some set of conflict(s), you must commit the result as a merge commit first, before you use git commit --amend to store a new and different merge result. That is, we start with:

          I--J   <-- br1 (HEAD)
         /
...--o--*
         \
          K--L   <-- br2

and run git merge br2, and we expect to end up with:

          I--J
         /    \
...--o--*      M   <-- br1 (HEAD)
         \    /
          K--L   <-- br2

To get this result after a conflict, you must not use git commit --amend. You may use either git commit or git merge --continue to make M, and these will finish off the rerere action that was started by the conflicted merge.

If you do use git commit --amend, what you would get is not a merge commit M but rather a new commit J':

            J'  <-- br1 (HEAD)
           /
          I--J
         /
...--o--*
         \
          K--L   <-- br2

but in fact Git says:

$ git commit --amend -m 'testing amend'
fatal: You are in the middle of a merge -- cannot amend.

(when I tested it, anyway).

If you get conflicts as a result of cherry-picking, the picture is a bit different, but the situation is similar:

...--o--o--I--J   <-- br1 (HEAD)
  \
   o--P--C--o--...   <-- br2

$ git cherry-pick <hash-of-C>
[merge conflicts occur]

Again, you do not want to git commit --amend at this point as that would create a new J':

             J'  <-- br1 (HEAD)
            /
...--o--o--I--J
  \
   o--P--C--o--...   <-- br2

rather than a new C':

...--o--o--I--J--C'  <-- br1 (HEAD)
  \
   o--P--C--o--...   <-- br2

The saved snapshot and commit messages for J' and C' are identical, but the parent of J' is (incorrectly) I, "losing" commit J.

Since there's no MERGE_HEAD file, it seems likely that Git will allow this commit, but you probably should not go about making it. (I did not test this particular case while writing this answer.)

  • Related