git rebase Interactive:将提交压缩在一起
我想要一个简单的解决方案来在交互式变基期间将两个合并提交压缩在一起。
我的存储库看起来像:
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
但是如果我有很多提交,这可能会变得复杂,你有更好的解决方案吗? 谢谢。
米尔德里德
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
这是一个老话题了,但我只是在寻找类似信息时遇到的。
类似于子树章鱼合并中描述的技巧对于此类问题来说,这是一个非常好的解决方案:
它将采用 my-feature 顶端存在的索引,并使用它从 Y 创建一个新的提交,并以“f”作为第二个父级。结果就像您从未执行过 M1,而是直接执行 M2 一样。
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:
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.
我来到这个主题是想压缩单个合并提交;所以我的回答对原来的问题没有多大用处。
我想要的是对 M1 合并进行变基并将所有内容压缩为 b 之上的单个提交。
我尝试了各种不同的组合,但这就是有效的:
这会将更改应用到可以提交它们的索引中
git 提交
I came to this topic wanting to squash a single merge commit; so my answer is not that useful to the original question.
What I wanted was to rebase the M1 merge and squash everything as a single commit on top of b.
I tried all kinds of different combinations but this is what worked:
This will apply the changes into the index where they can be committed
git commit
使用原始合并提交的树对象将确保内容保持不变。 commit-tree 可用于使用所需的父级和相同的内容进行新的提交。但是,要使 fmt-merge-msg 生成正常的合并消息,您需要首先软重置回 Y。这是用通用配方打包的所有内容:
启用:
\t\t'"branch $merge_branch" | git fmt-merge-msg | git commit-tree -p $parent1 -p $parent2 -F - $tree) git reset --hard $commit这是一个可以放在 ~/.fmt-merge-msg 中的别名。 gitconfig:
启用:
Using the tree object of the original merge commit will ensure the content is left unchanged. commit-tree can be used to make a new commit with the desired parents and the same content. But, for fmt-merge-msg to produce a normal merge message, you'll need to first soft reset back to Y. Here is everything packaged up with a generic recipe:
To enable:
\t\t'"branch $merge_branch" | git fmt-merge-msg | git commit-tree -p $parent1 -p $parent2 -F - $tree) git reset --hard $commitHere is an alias that can be put in your ~/.gitconfig:
To enable:
对于我最新的 git 版本,上述方法都不起作用。在我的例子中,以下方法达到了目的:
不过,您必须首先将提交消息写入文件 commit_msg 。
None of the mentioned methods works for me with a recent git version. In my case the following did the trick:
You'll have to write the commit message to the file commit_msg first, though.
在我看来,最好的方法是将自己置于合并提交之上,撤消顶部提交并修改对先前合并提交的更改。
您将使用以下命令撤消 git-commit:
或
然后使用:
然后使用以下命令检查结果:
您应该看到第一个合并提交现在包含了这两项更改。
In my opinion, the best method is to place yourself on top of the merge-commits and undo the top commit and amend the changes to the previous merge-commit.
You will undo a git-commit with the following command:
or
Then use:
Then check the results with:
You should see that the first merge-commit now has both changes included.