Rebase到Rebase / Squash

问题描述 投票:1回答:1

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

  1. 在git分支上做一些工作(my-first-work
  2. 推高到github
  3. some-further-work工作的基础上开始一个新的分支(my-first-work

未指定的时间过去了

  1. 批准者将my-first-work重新加入或压缩到master
  2. 这会创建新的提交,即git不会将其视为与我所基于的东西等效,即使最终结果相同(即master的头部与my-first-work的头部相同)
  3. 我运行git rebase mastersome-further-work移动到master
  4. 我所基于的my-first-work的承诺现在都与已经被挤压/合并的东西发生冲突

目前,我通过使用git rebase -i master来解决这个问题,然后将所有提交删除到my-first-work的头部。这将在master之上干净地重放其他提交。

有更清洁的解决方案吗?有没有办法让git自动识别何时发生了rebase / squash(如4)?

git git-rebase git-squash
1个回答
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中的快照是*-plus-some-changes,而提交A'中的快照添加对后来的提交进行相同的更改。

由于我们使用我们闪亮的新提交A'(有不同的哈希)支持旧的沉闷的A,我们需要将B复制到B',并将C复制到C',一旦我们完成,我们需要我们的名字topic指向not到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'C复制到C'
  5. 将当前分支名称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 checkout feature2; git rebase upstream/master,您的Git将枚举提交G-F-E-D-C-B-A-*-...,枚举ABC-*-...,从第一个中减去第二个,并留下指示复制G-F-E-D-C-B-A链。

更高级的rebase命令是:

git checkout feature2
git rebase --onto upstream/master feature1

这样做是将目标参数--Git将从limit参数开始复制的位置 - 分开。目标是upstream/master(Git文档称之为on参数)。限制论证现在是feature1。如果您愿意,可以使用commit C的原始哈希ID。 Git只需知道:我从哪里开始淘汰这些提交枚举? (令人困惑的是,Git文档将此称为上游参数。)

正如你所看到的,这现在敲出了C-B-A-*提交而不仅仅是*提交,因此在复制之后,你有:

               D'-E'-F'-G'  [in progress]
              /
...--o--*--ABC   <-- upstream/master
         \
          A--B--C   <-- feature1
                 \
                  D--E--F--G   <-- feature2

现在Git可以将标签feature2G剥离并将其贴在G2上。


1技术上,git rebase还有很多,特别是现在有了新的--rebase-merges选项。不过,我有一个线性的提交链仍然是它的主要用途。

作为一个很好的奖励,rebase通常可以告诉他们是否已经将你的A-B-C链条复制到他们自己的A'-B'-C'链。但那只是通常的。 Rebase永远不会告诉他们他们已经把你的A-B-C压扁到他们自己的ABC,所以在这种情况下你被卡住了--onto

© www.soinside.com 2019 - 2024. All rights reserved.