Catsunami Catsunami - 3 months ago 15
Git Question

Git: how to amend an old merge (in a series of merges)?

I have a situation that sort of looks like this:

(branch 1) A -- B -- C
\
(dev br) E -- F -- G -- H
/ /
(branch 2) I -- J -- K -- L


This all worked fine. Unfortunately I figured out that I need to make a change to F (post commit between J and E), so I'm trying to accomplish the following:

(branch 1) A -- B -- C
\
(dev br) E -- F' -- G -- H
/ /
(branch 2) I -- J -- K -- L


My initial approach was to make another commit with the fixes on the
dev br
and do a rebase and squash it into F. However, this makes me resolve all merge conflicts from the C-G merge and the L-H merge again, which were fairly involved and I don't want to do them.

Next attempt, I basically checked out F, made my changes, and then cherry picked G on top. This made the correct changes and I didn't have to resolve too much. However, now git doesn't think that this is a merge (because I guess it was cherry picked, though I did supply the -m command). Is there a way not to lose the merge info?

I tried it with rebase as well, running it as
git rebase --onto F' C G
, but that also makes me go through all previous commits (A-C, but in reality there are many more) and solve their rebase conflicts again.

How do I do this without going insane? I'm sure there must be a proper way to do this.

Answer

I'll give it until tomorrow to see if anyone knows any sweet git tricks.

OK: one "Git trick" for you.
From what you describe, the cherry-pick is the most promising approach.

"However, now Git doesn't think that this is a merge".

But it can.

After having modify F into F':

  • make your cherry-pick without committing right away:

    git cherry-pick --no-commit -m 1 vG
    git stash
    
  • add the merge information (without redoing any merge, with the ours strategy)

    git merge -s ours -m "Gp" branch1
    git stash pop
    git commit --amend --no-edit
    

That will create a G' (G prime, or Gp), which records a merge from branch1, while keeping the result of the cherry-pick intact.

You might have to repeat that for H, and you are done.

(The OP Catsunami mentioned below in the comments the need for git stash in order to allow for the merge to proceed)