Rewrite a merge commit into a squash merge commit

Marc picture Marc · Oct 4, 2013 · Viewed 8.6k times · Source

I made a merge of a long lived branch and it took me time to complete the merge because of the conflicts resolution.

I found out that I cannot publish my work with git-svn: git svn rebase will rebase all the commits of the merged branch instead of submitting one single merge commit. I discovered git merge --squash a bit too late...

Is it possible to change (rebase interractive ?) the merge commit into a "squash merge" commit without loosing all the conflicts resolution work already done (i.e. without triggering a new merge as I had not enabled the rerere tool) ?

Answer

SteveMellross picture SteveMellross · Apr 4, 2020

If you have merged and with git merge (--no-ff) and want to turn it into the equivalent of a git merge --squash, you can use the following process (assuming the merge commit is the most recent commit on the branch):

  • Ensure you have the affected branch checked out.
  • git reset --hard HEAD~1 (Resets the branch to the commit before the merge. Don't worry, it's not lost!)
  • git cherry-pick -m 1 HEAD@{1} (Cherry-picks the merge commit you just removed as a normal commit, based on the diff between it and this branch)

In addition to preserving any conflict resolution done during the merge, it will also preserve the original merge commit information (message, author, date, etc), making it very useful for fixing incorrect merges from tools like BitBucket that generate consistent commit messages.

We have a squash-commit only policy so I end up using this occasionally whenever someone accidentally selects the normal merge option from a BitBucket PR. Or clicks the frustratingly tempting "Merge" button on the Slack BitBucket bot that does not give you a choice of merge strategies...