我希望有一个简单的解决方案,可以在交互式rebase期间将两个合并提交压缩在一起。
我的存储库看起来像:
X --- Y --------- M1 -------- M2 (my-feature)
/ / /
/ / /
a --- b --- c --- d --- e --- f (stable)
也就是说,我有一个my-feature
分支,最近两次合并,没有真正的提交。我不只是想重新定义my-feature
分支,因为它是它自己的已发布分支,我只想将最后两个合并提交压缩成一个(尚未发布那些提交)
X --- Y ---- M (my-feature)
/ /
/ /
a --- ... -- f (stable)
我试过了:
git rebase -p -i M1^
但我得到了:
Refusing to squash a merge: M2
我最终做的是:
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
现在,新的合并提交不再被视为合并提交(它只保留第一个父级)。所以:
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
但如果我有很多提交,这会变得复杂,你有更好的解决方案吗? 感谢。
米尔德里德
答案 0 :(得分:48)
这是一个古老的主题,但我在搜索类似信息时遇到了它。
类似于Subtree octopus merge中描述的技巧,是解决此类问题的一个非常好的解决方案:
git checkout my-feature
git reset --soft Y
git rev-parse f > .git/MERGE_HEAD
git commit
这将采用我在我的功能的尖端存在的索引,并使用它来创建Y的新提交,其中'f'作为第二个父级。结果就像你从未执行过M1一样,但直接执行M2。
答案 1 :(得分:8)
如果您尚未发布最后两次合并提交,则可以执行重置和简单合并。
git reset --hard Y
git merge stable
答案 2 :(得分:5)
我来到这个主题想要压缩单个合并提交;所以我的答案对原来的问题没那么有用。
X
\
\
a --- b --- c --- M1 (subtree merge)
我想要的是重新定义M1合并并将所有内容压缩为b之上的单个提交。
a --- b --- S (include the changes from c, X and M1)
我尝试了各种不同的组合,但这是有效的:
git checkout -b rebase b (checkout a working branch at point b)
git merge --squash M1
这会将更改应用到可以提交的索引中 git commit
答案 3 :(得分:0)
对于我最近的git版本,所提到的方法都不适用。在我的情况下,以下做了诀窍:
git reset --soft Y
git reset --hard $(git commit-tree $(git write-tree) -p HEAD -p stable < commit_msg)
但是,您必须首先将提交消息写入文件commit_msg。