I wanted to have a simple solution to squash two merge commits together during an interactive rebase.
My repository looks like:
X --- Y --------- M1 -------- M2 (my-feature) / / / / / / a --- b --- c --- d --- e --- f (stable)
That is, I have a my-feature
branch that has been merged twice recently, with no real commits in between. I don't just want to rebase the my-feature
branch since it is a published branch of its own, I just want to squash together the last two merge commits into one (haven't published those commits yet)
X --- Y ---- M (my-feature) / / / / a --- ... -- f (stable)
I tried:
git rebase -p -i M1^
But I got:
Refusing to squash a merge: M2
What I finally did is:
git checkout my-feature git reset --soft HEAD^ # remove the last commit (M2) but keep the changes in the index git commit -m toto # redo the commit M2, this time it is not a merge commit git rebase -p -i M1^ # do the rebase and squash the last commit git diff M2 HEAD # test the commits are the same
Now, the new merge commit is not considered a merge commit anymore (it only kept the first parent). So:
git reset --soft HEAD^ # get ready to modify the commit git stash # put away the index git merge -s ours --no-commit stable # regenerate merge information (the second parent) git stash apply # get the index back with the real merge in it git commit -a # commit your merge git diff M2 HEAD # test that you have the same commit again
But this can get complicated if I have many commits, do you have a better solution ? Thanks.
Mildred
Squash commits together. Two other commands rebase interactive offers us are: squash ( s for short), which melds the commit into the previous one (the one in the line before) fixup ( f for short), which acts like “squash”, but discards this commit's message.
In case you are using the Tower Git client, using Interactive Rebase to squash some commits is very simple: just select the commits you want to combine, right-click any of them, and select the "Squash Revisions..." option from the contextual menu.
Merge squash merges a tree (a sequence of commits) into a single commit. That is, it squashes all changes made in n commits into a single commit. Rebasing is re-basing, that is, choosing a new base (parent commit) for a tree.
Squashing by Interactive Rebase. Git's interactive rebase will list all relevant commits in the default editor. In this case, those are the commits we want to squash. Then we can control each commit and commit message as we want and save the change in the editor.
This is an old topic, but I just ran across it while looking for similar information.
A trick similar to the one described in Subtree octopus merge is a really good solution to this type of problem:
git checkout my-feature git reset --soft Y git rev-parse f > .git/MERGE_HEAD git commit
That will take the index as it exists at the tip of my-feature, and use it to create a new commit off of Y, with 'f' as a second parent. The result is the same as if you'd never performed M1, but gone straight to performing M2.
if you haven't published the last two merge commits, you could do a reset and a simple merge.
git reset --hard Y git merge stable
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With