变基到变基/壁球

时间:2019-03-08 11:39:08

标签: git git-rebase git-squash

这是我遇到的常见情况,我正在寻找一种干净的解决方案。

  1. 在git分支(my-first-work)上做一些工作
  2. 上推github
  3. 根据工作some-further-work的顶部,开始新的分支(my-first-work

未指定的时间间隔

  1. 批准人将my-first-work变基或压榨到master
  2. 这将创建新的提交,即使最终结果相同(即master的头部与{{1的头部)相同,git也不会将其视为我所基于的东西}})
  3. 我运行my-first-workgit rebase master移到some-further-work
  4. 我现在基于master所做的提交都与已经被压榨/合并的内容冲突

当前,我通过使用my-first-work来解决此问题,然后删除直到git rebase -i master头的所有提交。这样可以干净地重播my-first-work顶部的其他提交。

是否有更清洁的解决方案?并有一种方法可以使git在发生变基/压扁(如4)时自动识别?

1 个答案:

答案 0 :(得分:1)

清洁程序在旁观者/工作人员的眼中(或手?),但是您可以使用git rebase --onto来分离出要复制的 放置副本的位置

请记住git rebase的意思是: 1 我有一个线性的提交链,如图1所示,我想复制到一个新的线性提交链,如下所示:如图2所示。完成复制后,我希望我的分支名称指向上次复制的提交。原始的A-B-C链即使仍然存在也不再有用。

[drawing 1]
...--o--*--o   <-- upstream/master
         \
          A--B--C   <-- topic

[drawing 2]
...--o--*--o   <-- upstream/master
            \
             A'-B'-C'  <-- topic

原始提交和副本之间的区别在于,原始提交基于提交*之前是upstream/master的提示。副本基于upstream/master的(新)提示。短语<基于> 在这里有两个含义:提交A父对象是提交*,而 的父对象>提交A'是后面的提交,而快照中的提交A*加上一些变化,而快照中的 commit A' same 更改添加到以后提交中。

由于我们使用有光泽的新提交A'(具有不同的哈希值)来支持旧的呆板A,因此我们需要将B复制到B' ,以及CC',一旦完成,我们需要我们的名字topic指向的不是最后复制的提交C,而不是C'

纯白的git rebase正是这样做的。我们说:

git checkout topic; git rebase upstream/master

告诉Git:

  1. 枚举从C开始并向后工作的所有提交。那是C然后B然后A然后*然后*之前的所有内容。
  2. 枚举从upstream/master开始并向后工作的所有提交。这是第二个o,然后是*,然后是*之前的所有内容。
  3. 将第二个列表中的所有内容从第一个列表中剔除。这样就淘汰了*和所有较早的提交。第二个o不在第一个列表中,但是没关系:如果插入,我们将其淘汰,但事实并非如此,因此我们什么也不做。现在,我们的列表为CBA
  4. 将列表反转以正确的顺序,然后一次将每个提交复制到新位置。新位置从upstream/master指向的提交开始。因此,这会将A复制到A',将B复制到B',然后{{ 1}}到C
  5. 将当前分支名称C'移出先前的位置,并像往常一样将其粘贴到新的提交链中。因此,这使topic指向到topic,而不是C'

在新情况下,您有:

C

他们在上游没有抓住您的...--o--* <-- upstream/master \ A--B--C <-- feature1 \ D--E--F--G <-- feature2 连锁店。相反,他们进行了自己的不同的A-B-C壁球提交。您从上游存储库中获取了它,所以现在有了:

ABC

如果仅运行...--o--*--ABC <-- upstream/master \ A--B--C <-- feature1 \ D--E--F--G <-- feature2 ,则Git将枚举提交git checkout feature2; git rebase upstream/master,枚举G-F-E-D-C-B-A-*-...,从第一个中减去第二个,然后留下复制{{1} }链。

发烧友的变基命令是:

ABC-*-...

此操作将 target 参数(Git开始复制的位置)与 limit 参数分开。现在 target G-F-E-D-C-B-A(Git文档将其称为 onto 参数)。现在 limiting 参数为git checkout feature2 git rebase --onto upstream/master feature1 。如果愿意,可以使用提交upstream/master的原始哈希ID。 Git只需要知道:我从哪里开始我的敲除这些提交枚举?(令人困惑的是,Git文档将此称为 upstream 参数。)

如您所见,这现在剔除feature1提交,而不仅仅是C提交,因此在复制之后,您将:

C-B-A-*

现在Git可以将标签* D'-E'-F'-G' [in progress] / ...--o--*--ABC <-- upstream/master \ A--B--C <-- feature1 \ D--E--F--G <-- feature2 上剥下来,然后贴在feature2上。


1 从技术上讲,G还有很多功能,尤其是现在有了新的G2选项。但是,这个我有一个线性的提交链仍然是它的 main 用途。

作为一个不错的奖励,rebase通常可以判断他们是否已经采用了您的git rebase链并将其复制到自己的--rebase-merges链。但这只是通常。 Rebase永远不会告诉他们他们已经将您的A-B-C压入自己的A'-B'-C'中,因此在这种情况下,您会陷入A-B-C的困境。 / p>