Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

git rebase interactive: squash merge commits together

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

like image 962
Mildred Avatar asked Nov 12 '09 21:11

Mildred


People also ask

How do you squash commits with rebase interactive?

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.

How would you squash multiple commits together using git merge -- squash?

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.

Is squash and merge the same as rebase?

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.

Does git rebase squash commits?

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.


2 Answers

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.

like image 128
Matt Avatar answered Oct 01 '22 14:10

Matt


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 
like image 23
bobDevil Avatar answered Oct 01 '22 14:10

bobDevil