[英]How git-merge and git-rebase behave with a topic branch forked off of another topic branch?
让我们假设存储库如下所示:
master
|
A--B--C--K--L--M
\
E-F-G
|\
| H-I-J
topicA |
topicB
什么会git merge topicB
在做的时候master
? 它仅适用提交H
, I
和J
吗? 还是从topicA
的初始分叉点开始的所有提交?
git rebase master topicA
做什么? 是否会导致此:
master
|
A--B--C--K--L--M
\
E'-F'-G'
|\
| H'-I'-J'
topicA |
topicB
或更多类似的东西?
master
|
A--B--C--K--L--M
\ \
\ E'-F'-G'
\ |
\ topicA
\
E-F-G-H-I-J
|
topicB
除了解析分支名称以提交ID之外,合并或重新设置基础都不关心任何分支标签指向的位置。 他们只看提交图。
我认为git merge
工作方式更容易理解。 除了为默认的合并提交消息保存分支名称之外, git merge
仅使用git rev-parse
查找提交ID。
对于第一个问题,在分支master
上给定git merge topicB
,git找到三个提交ID:
HEAD
解析为提交M
(分支master
上最尖端的提交;这也是运行git rev-parse HEAD
看到的提交ID)。 topicB
解析为提交J
(分支topicB
上最尖端的提交;这也是运行git rev-parse topicB
看到的提交ID)。 C
找到合并基础后,git然后运行两个git diff
:一个在merge-base和HEAD
提交之间(以查看“您的分支”做了什么),另一个在merge-base和topicB
提交之间(以查看其“什么”)分支”)。 它结合了两组更改,如果没有冲突(或者可以通过git rerere
解决),则进行一个新提交,其两个父级(按此顺序)是当前HEAD
提交和topicB
提交。 进行新的提交将照常更新当前分支,以便HEAD
现在指向新的提交(或更准确地说, HEAD
仍指向master
,而master
指向新的提交)。
这个问题:
它仅适用提交H,I和J吗? 还是从topicA的初始分叉点开始的所有提交?
意味着对git的合并算法有根本的误解:git不会查看任何中间提交。 在此情况下,它仅查看此处标识的三个提交: M
, J
和C
Git可以像这样“欺骗”,因为就该提交的源树内容而言,每个提交都是完全独立的。
Rebase比较复杂(上面的第二个猜测中您已经正确了,但是无论如何,我们都要经历一下)。
它仍然使用相同的“通过git rev-parse
分支名称解析为ID”的技巧,但是它使用了更复杂的git rev-list
变体。 git rev-list
作用是对提交图进行计算集操作(再次将其实际放入图本身时将忽略任何标签)。
给定git rebase master topicA
,我们(好吧,无论如何, 我 :-))首先必须检查rebase
文档 ,在该文档中我们发现master
被视为<upstream>参数,而topicA
被视为<branch>参数,并且最后一个参数的作用是先运行git checkout <branch>
,然后像未提供它一样继续进行。 因此,从心理git checkout topicA
,我们可以假设您首先通过git checkout topicA
,然后运行git rebase master
。 <upstream>参数为master
而HEAD
引用分支topicA
因此它标识提交G
过去,在git rebase
--fork-point
,要确定接下来会发生什么比较容易。 今天,根据文档,您必须确定是否已启用--fork-point
。 因为您确实提供了一个实际的<upstream>参数,所以默认情况下它是禁用的:仅当您在命令行中输入--fork-point
时才启用该参数。 您没有;因此,我们不必深入研究--fork-point
( --fork-point
,yay!:-)的奥秘。 因此,这里发生的是,rebase本质上运行git rev-list master..HEAD
来获取要复制的提交列表。 该列表列出了提交E
, F
和G
,因为它们是HEAD
而不是master
可以到达的集合中的提交。
然后,rebase进程将在--onto
参数(如果有)(没有)提交的提交处分离HEAD
,或者在<upstream>参数给出的提交处分离HEAD
。 那是master
所以这是提交M
从这里开始,基本上只对早期发现的每个提交进行重定位,即可为您提供E'
, F'
和G'
。 如果所有这些都正常工作,则git进行基础调整的最后一步是将原始当前分支(再次是topicA
)指向最后的提交G'
。 没有其他标签更改,因此您得到了绘制的最终图形。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.