我遇到了一个有趣的问题,我让我的主人试图赶上上游分支。但是我想在整个过程中的特定点测试我的主人,所以我确保在某些点上我只能在上游转换为主人。
假设以下状态:
--F--G--H--> master
/
/
----A--B--C--D--E--I--J--> upstream
我想首先重新定义C和D,然后进行测试。所以我这样做:
$ git checkout upstream
$ git checkout D
$ git checkout -b upstreamD
$ git rebase -i master
$ git checkout master
$ git merge upstreamD
这显示了C和D到rebase。成功改造后,我有:
--F--G--H--C--D--> master
/
/
----A--B--C--D--E--I--J--> upstream
^
upstreamD
然后我删除了上游因为我在测试时不再需要它等(因为我总能得到它)。
$ git branch -d upstreamD
$ git branch -d upstream
$ git remote rm upstream
我做我的测试,因为一切都很好,我回去使用新创建的遥控器抓住我的上游,并把它的主人放在分支上游。
所以,现在我觉得我有类似的东西(通知大师和上游有更多的提交):
--F--G--H--C--D--K--L--> master
/
/
----A--B--C--D--E--I--J--M--N--> upstream
我想要更多一点,所以我执行上面的相同程序:
$ git checkout upstream
$ git checkout J
$ git checkout -b upstreamJ
$ git rebase -i master
然而,现在我要修改一些东西,比如:C,E,I,J。奇怪的是,我只是期待E,I,J。C已经掌握了(即使在不同的SHA1下,因为历史不同。)
在http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html它说,我引用:
如果上游分支已包含您所做的更改(例如, 因为你邮寄了一个上游应用的补丁,然后那个 提交将被跳过。
我无法找到解释git如何执行此跳过的任何地方。它是如何检查C是否已经处于主数据库中,为什么它决定C应该再次重新设置而D不应该呢?
答案 0 :(得分:4)
请注意,HEAD中引入与HEAD中的提交相同的文本更改的任何提交都将被省略(即,将跳过已使用不同提交消息或时间戳的上游接受的修补程序)。
(似乎是通过git format-patch
实施的,特别是--ignore-if-in-upstream
选项。)
这意味着补丁必须在文本上相同(只有补丁,而不是提交元数据或SHA ID等),以便rebase自动跳过它们。
我怀疑在上面的例子中,提交C可能存在您必须解决的冲突;因此,补丁将是不同的。如果提交D没有冲突,它仍然在文本上是相同的,那么为什么rebase在没有跳过C时跳过它。
在我看来,处理此方案的最佳方法是使用--onto
的{{1}}选项,如下所示:
git rebase
其中D是您最后一次提交的提交。还有其他方法;以交互方式重新定位并删除您已知的已提交的提交。
我认为git rebase --onto master D
的自动跳过逻辑是“尽力而为”的逻辑;当它运作时它很棒,但正如你所见,你必须为它没有做好准备。
HTH。