1

我遇到了一个有趣的问题,我的主人试图赶上上游分支。但是我想在沿途的特定点测试我的主人,所以我确保我只在某些点上游重新定位到主人。

假设以下状态:

          --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 变基。成功变基后,我有:

          --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 已经在 master 中(即使在不同的 SHA1 下,因为历史不同)。

http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html它说,我引用:

如果上游分支已经包含您所做的更改(例如,因为您邮寄了一个应用于上游的补丁),那么该提交将被跳过。

我找不到任何解释 git 如何执行此跳过的地方。它如何检查 C 是否已经在 master 中,为什么它决定 C 应该再次变基而 D 不应该?

4

1 回答 1

4

git-rebase(1)

请注意,HEAD 中引入与 HEAD.. 中的提交相同的文本更改的任何提交都将被忽略(即,将跳过已在上游接受的具有不同提交消息或时间戳的补丁)。

(这似乎是通过 实现git format-patch的,特别是--ignore-if-in-upstream选项。)

这意味着补丁必须在文本上相同(只有补丁,而不是提交元数据或 SHA id 等),以便 rebase 自动跳过它们。

我怀疑在您上面的示例中,提交 C 可能存在您必须解决的冲突;因此,补丁会有所不同。如果提交 D 没有冲突,它在文本上仍然是相同的,因此当它没有跳过 C 时,为什么 rebase 跳过它。

在我看来,处理这种情况的最佳方法是使用--ontofor 选项git rebase,如下所示:

git rebase --onto master D

其中 D 是您重新调整的最后一次提交。还有其他方法;以交互方式重新设置基础并删除您知道已经存在的提交是其中之一。

我认为自动跳过逻辑git rebase是“尽力而为”的逻辑;当它起作用时它很棒,但是正如您所看到的,您必须为不起作用的情况做好准备。

HTH。

于 2012-10-11T18:19:11.797 回答