这是我遇到的常见情况,我正在寻找一个干净的解决方案。
my-first-work
)some-further-work
工作的基础上开始一个新的分支(my-first-work
)未指定的时间过去了
my-first-work
重新加入或压缩到master
master
的头部与my-first-work
的头部相同)git rebase master
将some-further-work
移动到master
my-first-work
的承诺现在都与已经被挤压/合并的东西发生冲突目前,我通过使用git rebase -i master
来解决这个问题,然后将所有提交删除到my-first-work
的头部。这将在master
之上干净地重放其他提交。
有更清洁的解决方案吗?有没有办法让git自动识别何时发生了rebase / squash(如4)?
清洁者是旁观者/工人的眼睛(或手?),但你可以使用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:
C
开始并向后工作的所有提交。那是C
然后B
然后A
然后*
然后*
之前的一切。upstream/master
开始并向后工作的所有提交。这是第二个o
,然后*
然后*
之前的一切。*
和所有早期的承诺。第二个o
不在第一个列表中,但是没关系:如果它存在的话,我们会把它击败,但事实并非如此。我们的名单现在是C
,B
和A
。upstream/master
指向的承诺。因此,这将A
复制到A'
,B
复制到B'
,C
复制到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 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可以将标签feature2
从G
剥离并将其贴在G2
上。
1技术上,git rebase
还有很多,特别是现在有了新的--rebase-merges
选项。不过,我有一个线性的提交链仍然是它的主要用途。
作为一个很好的奖励,rebase通常可以告诉他们是否已经将你的A-B-C
链条复制到他们自己的A'-B'-C'
链。但那只是通常的。 Rebase永远不会告诉他们他们已经把你的A-B-C
压扁到他们自己的ABC
,所以在这种情况下你被卡住了--onto
。