How to linearize split merge history in Git?

It should be very obvious, but I haven't found a way to do it. Each tutorial describes reloading to the top of an existing branch or a simple interactive rewrite and that's it. Suppose I have a diamond shape like this in git shape:

*   949430f Merge commit (D) (HEAD, mybranch)
|\  
| * e6a2e8b (C)
* | 3e653ff (B)
|/  
*   9c3641f Base commit (A)

      

and I want to archive history, for example:

*   949430f Combined commit (BCD)
|  
*   9c3641f Base commit (A)

      

Blocking B and C can be melted or discarded altogether, it doesn't matter, I only want to keep the result. Also I do NOT want to revert commits due to nasty conflicts.

Here's what I've tried:

1) I cannot argue that by simply twisting B and C

git rebase -i HEAD~2
...
p 3e653ff (B)
f e6a2e8b (C)
...
Could not apply a91f3a4

      

Well, this is somewhat understandable, there are some conflicts.

2) I can't do it by crushing.

git rebase -i -p HEAD~3
...
pick 9c3641f Base commit (A)
f 3e653ff (B)
f e6a2e8b (C)
pick 949430f Merge commit (D)
...
error: unable to match a91f3a4...

      

3) I can't even drop B and C

git rebase -i -p -m HEAD~3
...
pick 9c3641f Base commit (A)
#pick 3e653ff (B)
#pick e6a2e8b (C)
pick 949430f Merge commit (D)
...
error: Commit 949430f is merged but option -m is not set.
fatal: cherry-pick failed
Could not pick 4f3e6231b5cecf57434613ca3afd2a21ba375eb9

      

Why? Here is the "-m" option ...

Does anyone know how to fix this problem?

+3


source to share


3 answers


You want git reset --soft

(plus the commit marked with aragar ). Despite the varying circumstances in the question, see this answer by VonC .



+6


source


I'll try to linearize the commit graph first and then compress them together:



$ git checkout commitA -b newbranch
$ git cherry-pick commitB
$ git cherry-pick commitC
[resolve any conflicts]
$ git rebase -i commitA
[change the command for commitC to 'squash']

      

+1


source


git rebase -i 9c3641f^ # 1 before base commit

      

then in the interactive editor

pick 9c3641f Base commit (A)
pick 3e653ff (B)
fixup e6a2e8b (C)
fixup 949430f Merge commit (D) (HEAD, mybranch)

      

Actually I expected the latter to not be present because the merge compilation disappears during interactive re-registration in my experience.

This will swallow B and C into one commit. D will disappear and you really don't want it, as it doesn't add any code.

This will give you the desired result. The conceptual thing you missed was that you need to keep the first commit (selection), but if you "fix" the other two, they will merge into it. You need to give them something to merge with this, this is not a basic commitment. So, you select the second and then the third merges into it, giving you two commits.

You can also do

git rebase -i 9c3641f

      

and then simply sees the fixing base in an interactive editor, but pick

and fixup

are the same for the remaining rows.

+1


source







All Articles