Convert merge into rebase without having to perform the merge again

tl;dr

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

Preserving merge commits during a rebase

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.

Leave a Comment