链式分支合并策略

时间:2017-12-22 10:29:40

标签: git merge

我从master创建了分支A.完成后我创建了拉取请求掌握。当A的工作正在审查中时,我开始处理基于分支A的任务,所以从分支A我创建了分支B.然后我将分支B合并到A并且想要将B合并到主人,但是冲突出现了。在这种情况下,避免冲突的最佳做法是什么?在A的拉取请求之前,两个分支都是本地的。

[编辑]

在分支A和B中编辑了同一行,那么为什么它不会自动合并?

enter image description here

1 个答案:

答案 0 :(得分:2)

Git (这里需要强调,因为你可能使用的不仅仅是Git本身)并没有一个"基础分支"的概念。

当您使用GitHub或Bitbucket上的网络界面来创建"拉取请求时,它是 Web界面,它选择上游'用于建议拉取请求的分支名称。 Git本身并不知道你会发出拉取请求。 1 所有Git都知道并关心提交,通常是通过哈希ID。

运行git merge时,选择两个提交,通常是两个分支提示。您可以通过git checkout选择一个,通常为git checkout <somebranch>。该提交将成为您的当前提交。这是Git调用 local --ours的提交;我通常称它为 L 为左,本地或--ours。 (请注意,如果您不在git checkout之前运行git merge,那么您现在检查的内容仍然您当前的提交,因此您选择 作为 L 提交。)

然后运行git merge <name-or-hash-id>。 Git将名称(如果您给它一个)转换为提交哈希ID。这是您选择其他提交的方式,Git有时会将其命名为远程其他--theirs提交,并且我会调用 R

Git使用 L R 提交哈希ID以及存储库中的所有其他提交来查找合并base 提交哈希ID。简而言之,这个合并基础提交是&#34;最近的&#34;承诺两个分支一起回来&#34;。 Git将在此处找到的提交取决于现有提交图的拓扑结构。

如果Git能够自己进行合并,Git会生成一个包含合并结果的新提交。新提交有两个父项,而不只是一个:第一个父项是您运行git merge L 的提交,第二个是 R 的提交。新提交在当前分支上进行,因此当前分支名称(您已检出的分支名称)现在指向新的合并提交。

您在上面绘制的图表很难解释:我无法从您的绘图中看出哪些提交可以从哪个分支提示提交,或者就此而言,哪些提交首先是分支提示。特别是你已经绘制了两个似乎是合并提交的提交,但我不知道早期(祖先)提交是左侧还是右侧。此外,您的文字描述了一个合并,而不是两个。假设先前提交是向左 - 那个时间从左到右流动,就像在这里 - 我在这里是如何在文本中绘制大部分图:

       o--o   o--o   <-- branch-B
      /    \ /
     | __---o   <-- branch-A
     |/
...--o   <-- master

但请注意,图只有一个合并提交,在这种情况下是名称branch-A指向的提交。名称branch-B指向顶行的最右侧提交。

在此特定示例中,branch-B包含图表中提取的每个提交,而branch-A包含除最近两次提交之外的所有提交,master包含只有底线上的提交加上导致该点的任何早期提交。提示branch-B(提交 L )和提示master(提交 R )的合并基础将是提示提交master,即提交 R 本身。因此,在分支git merge上运行branch-B将选择它作为合并基础。合并将是微不足道的(但事实上被拒绝),因为不存在合并冲突。 2 因此,显然不是你在做什么,显然不是正确的图形。 / p>

如果没有正确的图表,就无法说出Git选择的合并基础。但是如果你确实遇到了合并冲突,那是因为当比较合并基础提交到提交 L 时,Git看到一个更改某个文件的某一行,然后比较合并基础提交提交 R ,Git看到对相同文件的相同行的不同的更改。 Git无法在这两个更改之间进行选择,因此它在合并冲突时停止,使文件的工作树版本应用了两个更改。现在由您来解决此冲突(以及任何其他冲突),git add正确的合并结果,并运行git merge --continue以完成合并;或运行git merge --abort以停止合并,并将事情恢复到Git尝试合并之前的状态。

1 虽然它们是相关的,但不要将这些外部提供的Web界面与git request-pull命令行命令混淆。那个内置到Git中,但它需要而不是Git,选择<start>提交。当GitHub为您做出选择时,他们正在使用Git本身无法获得的信息。具体来说,GitHub知道 - 已经记录了自己,在一个位置它有效地保密了Git - 当你点击GitHub&#34; fork&#34;按钮。他们(GitHub)也控制该上游项目的Git存储库,因此他们可以查看它并选择<start>。但他们这样做; Git没有。

2 请记住,在计算合并基础提交后,Git有效运行:

git diff --find-renames <base> L   # see what we did on --ours
git diff --find-renames <base> R   # see what they did on --theirs

然后尝试将这两组变化合并为一个大的&#34;每个人的变化,因为基地&#34;更改集,并将组合更改应用于<base>提交中的任何内容。我们刚刚声称<base> R 相同的提交,因此这里一定不会有任何更改。这种合并的结果将完全匹配commit L 。事实上,Git会说&#34;已经是最新的&#34;并且拒绝做任何事情,对于这种情况。