繁体   English   中英

git-merge和git-rebase如何与另一个主题分支派生的主题分支一起工作?

[英]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 它仅适用提交HIJ吗? 还是从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不会查看任何中间提交。 在此情况下,它仅查看此处标识的三个提交: MJC 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>参数为masterHEAD引用分支topicA因此它标识提交G

过去,在git rebase --fork-point ,要确定接下来会发生什么比较容易。 今天,根据文档,您必须确定是否已启用--fork-point 因为您确实提供了一个实际的<upstream>参数,所以默认情况下它是禁用的:仅当您在命令行中输入--fork-point时才启用该参数。 您没有;因此,我们不必深入研究--fork-point--fork-point ,yay!:-)的奥秘。 因此,这里发生的是,rebase本质上运行git rev-list master..HEAD来获取要复制的提交列表。 该列表列出了提交EFG ,因为它们是HEAD而不是master可以到达的集合中的提交。

然后,rebase进程将在--onto参数(如果有)(没有)提交的提交处分离HEAD ,或者在<upstream>参数给出的提交处分离HEAD 那是master所以这是提交M 从这里开始,基本上只对早期发现的每个提交进行重定位,即可为您提供E'F'G' 如果所有这些都正常工作,则git进行基础调整的最后一步是将原始当前分支(再次是topicA )指向最后的提交G' 没有其他标签更改,因此您得到了绘制的最终图形。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM