Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rewrite a merge commit into a squash merge commit

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) ?

like image 305
Marc Avatar asked Oct 04 '13 10:10

Marc


2 Answers

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...

like image 182
SteveMellross Avatar answered Sep 28 '22 16:09

SteveMellross


I was in a similar issue and was able to create a squashed commit by simply resetting and recommitting the change.

Starting layout:

*   06074985 (HEAD -> test1) Merge branch 'test2' into test1
|\
| * eb2aa088 (test2) test2 commit
* | c83180c8 test1 commit
|/
* b6628265 (master) base commit

git commands: git branch temp (so I don't loose the merge commit) git reset HEAD~1 git add . git commit -m "Squash commit" git diff temp (just to make sure nothing changed)

Ending layout:

* 5e229615 (HEAD -> test1) squash commit
| *   06074985 (temp) Merge branch 'test2' into test1
| |\
|/ /
| * eb2aa088 (test2) test2 commit
* | c83180c8 test1 commit
|/
* b6628265 (master) base commit
like image 38
Cemafor Avatar answered Sep 28 '22 17:09

Cemafor