当我合并两个分支的文件在同一行上具有差异时,不会发生冲突。

时间:2018-08-02 01:55:47

标签: git git-merge git-merge-conflict

考虑有一个分支A。我从分支A创建了两个分支A1,A2。再次从分支A2创建了分支A21。我更改了X文件中的第2行,并提交并推送到A21。现在,我将这些更改合并为A2。现在,我将结帐更改为A2。当我合并原点/ A时,没有冲突。我了解到,在合并期间,如果同一行中的差异或文件被删除,则会发生冲突。但是在上述情况下,合并后在A2中所做的更改保持不变,也不会发生冲突..任何人都可以解释原因。

3 个答案:

答案 0 :(得分:2)

首先:不要查看分支名称。查看 commits 和提交图。使用图形之后,您将仅使用名称来查找提交本身。使用图形查看器,或运行git log --graph(也许也使用--all --decorate --oneline)。您将看到图像或带有连接提交到其 parent 提交的行的文本,形成树或图结构:

*    a123456  last commit on A1
*    a123457  another commit on A1
| *  a2fedcb  last commit on A2
|/
*  a0dead0  latest shared commit reachable from both A1 and A2
.
.
.

例如,或查看下面从this answerViewing full version tree in git的图片。

一旦有了图形,它就会相对清楚地明白合并基础的含义。两个特定提交的合并基础是两个分支共享的提交。在上面的输出中,将提交a0dead0

如果我们重新水平绘制图形,则可能更清楚两个分支的分支方式:

          o--...--X   <-- you-are-on-this-branch (HEAD)
         /
...--o--*
         \
          o--...--Y   <-- you-ask-to-merge-this

这里,提交*是合并的基础,提交X(您现在已签出的提交)是HEAD,提交Y是另一个提交您要合并。

现在,git merge的工作方式实质上是从合并库本身开始。 Git提取合并基础提交,然后查看分支提示提交XY。 Git 比较合并基础以提交X,以查看所做的事情:

git diff --find-renames <hash-of-*> <hash-of-X>

然后,Git比较合并基础以提交Y,以查看他们做了什么:

git diff --find-renames <hash-of-*> <hash-of-Y>

Git现在只需将这两组更改组合,将它们全部应用于合并基础中的所有内容,并且,如果一切顺利,则进行新的合并提交,从而将当前分支移动为好吧:

          o--...--X
         /         \
...--o--*           M   <-- you-are-on-this-branch (HEAD)
         \         /
          o--...--Y   <-- you-ask-to-merge-this

合并的两个父级是按此顺序合并的两个提交,即XY

如果Git可以合并更改,则合并成功

如果Git无法合并更改,则合并失败

如果您和他们将相同更改为相同文件相同行,则Git可以将这两个更改组合在一起只需一份副本即可轻松完成。这就是Git所做的。

如果您对合并基础中的相同行进行了不同更改(提交*),则会产生冲突。

Git可以优化整个流程,通常根本不需要物理上提取提交*,但是原则上,这就是合并的过程。


gitk图片示例)

image from stackoverflow.com/a/18287861/1256452

答案 1 :(得分:0)

除了@torek所说的以外,git即使更改是相同的,即使更改是独立进行的,也将无冲突地处理合并。

在这里,我分别在branch1branch2中的同一文件中进行相同的更改,然后将branch2合并到branch1

/mnt/c/git/ConsoleApp1 (branch1)>git commit -a -m "Adding Foo in branch1"
[branch1 c03dcc2] Adding Foo in branch1
 1 file changed, 4 insertions(+)
/mnt/c/git/ConsoleApp1 (branch1)>git checkout develop
error: pathspec 'develop' did not match any file(s) known to git.
/mnt/c/git/ConsoleApp1 (branch1)>git checkout master
Switched to branch 'master'
/mnt/c/git/ConsoleApp1 (master)>git checkout -b branch2
Switched to a new branch 'branch2'
/mnt/c/git/ConsoleApp1 (branch2)>git commit -a -m "Adding Foo in branch2"
[branch2 d433128] Adding Foo in branch2
 1 file changed, 4 insertions(+)
/mnt/c/git/ConsoleApp1 (branch2)>git merge branch1
Merge made by the 'recursive' strategy.

结果:无冲突。

答案 2 :(得分:0)

在您的描述中,您仅谈论单个更改:

  

我更改了X文件中的第2行,并提交并推送到A21。

您永远不会说类似“ ...,并且在分支A上,我将X文件中的第2行更改为其他内容并提交了。”

如果这是真实的情况(即游戏中只有一个更改),那么就不会发生冲突。