I made a mistake: I should have used git pull --rebase
, but I issued a simple git pull
, merged everything and now have a merge commit at the HEAD of my branch.
I want to get rid of that merge commit and I thought I'd just issue a git rebase -i HEAD~3
, move my last local commit to the top and squash the merge commit into it. Alas, the merge commit is not available for squashing. If I do this, I get into intermediate states where I need to do the merge again, which is a lot of work.
Is there a way out of this without having to perform the merge again? It seems it should be possible to use the merge commit in some way?
Even if you can include merge commits in a rebase, you can't squash merge commits. Git will let you know by saying:
Refusing to squash a merge: <SHA-1>
What you can do in order to keep the changes made during the merge is to convert the merge commit into a normal commit. At that point you can squash it like any other commit.
Assuming HEAD
is pointing to the merge commit:
git reset --soft HEAD~1 # Keeps changes in the index
git commit # Create a new commit, this time not a merge commit
git rebase -i HEAD~4 # Do an interactive rebase and squash the new commit
In general, you can preserve merge commits when doing a rebase using git rebase -p
.
However, its purpose is to replay the commits leading up to the merge. Any changes that are part of the merge commits themselves (e.g. conflict resolutions) aren't preserved.
Here's from the documentation:
-p
--preserve-merges
Recreate merge commits instead of flattening the history by replaying commits a merge commit introduces. Merge conflict resolutions or manual amendments to merge commits are not preserved.
This uses the--interactive
machinery internally, but combining it with the--interactive
option explicitly is generally not a good idea unless you know what you are doing (see BUGS below)
The bug the documentation is referring to is triggered by reordering commits.