问题
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
回答1:
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.
回答2:
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
回答3:
I came to this topic wanting to squash a single merge commit; so my answer is not that useful to the original question.
X
\
\
a --- b --- c --- M1 (subtree merge)
What I wanted was to rebase the M1 merge and squash everything as a single commit on top of b.
a --- b --- S (include the changes from c, X and M1)
I tried all kinds of different combinations but this is what worked:
git checkout -b rebase b (checkout a working branch at point b)
git merge --squash M1
This will apply the changes into the index where they can be committed git commit
回答4:
None of the mentioned methods works for me with a recent git version. In my case the following did the trick:
git reset --soft Y
git reset --hard $(git commit-tree $(git write-tree) -p HEAD -p stable < commit_msg)
You'll have to write the commit message to the file commit_msg first, though.
来源:https://stackoverflow.com/questions/1725708/git-rebase-interactive-squash-merge-commits-together