Git rebase重复补丁检测实现

时间:2012-10-11 16:35:09

标签: git rebase

我遇到了一个有趣的问题,我让我的主人试图赶上上游分支。但是我想在整个过程中的特定点测试我的主人,所以我确保在某些点上我只能在上游转换为主人。

假设以下状态:

          --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不应该呢?

1 个答案:

答案 0 :(得分:4)

来自git-rebase(1)

  

请注意,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。