如果我有一个新的干净项目(主文件),并且添加了一个包含以下内容的新文件:
Master:test.txt
"123"
现在,我正在创建一个名为“ MyBranch”的新的分支分支,然后更改文件的内容:
MyBranch:test.txt
"193"
现在我要合并Mybranch --> Master
,
在这种情况下,我不知道这将是成功的合并还是冲突。 我已经看到了冲突和成功合并但仍然找不到黄金法则的情况。
问题
git什么时候引发冲突与成功合并?
答案 0 :(得分:3)
git引发冲突。
根据您的情况,由于您仅在Mybranch
中进行了一次编辑,因此合并时不会出现冲突。
如果在Master上进行了一次新的提交,在我尝试将其合并之前,我将文本更改为“ 987” 并提交了该代码,那么我们将发生冲突。
有用的资源:https://www.atlassian.com/git/tutorials/using-branches/git-merge
答案 1 :(得分:2)
总的来说,当具有两个具有相同共同祖先的分支,并且每个分支对于给定数量的行具有一组不同的更改时,就会发生冲突。
所以....如果您有一个共同的祖先A,则分支B和C并从A到B从文件中删除了5行...并且在A和C之间您修改了这5行中的任何一条,您会发生冲突。有许多种冲突。一种方式修改5行,另一种方式修改相同的5行..您合并,繁荣!还有其他类型的冲突,例如:在一个文件上编辑5行...在另一分支上删除文件。合并:繁荣!
如果一个分支上有一组更改,而另一个分支上没有更改,则不会有冲突。
答案 2 :(得分:1)
与eftshift0 says一样,尽管用不同的词表示,但这里的窍门是合并中没有两个输入,但有三个输入。
您将过程描述为:
master
上创建新的提交MyBranch
MyBranch
上创建新的提交运行:
git checkout master
git merge MyBranch
但这并不是发展的趋势。通常更像是:创建三个分支,开始对其进行创建,再创建六个,对其中一些进行处理,删除其中一些,创建其他,对其中几个进行一段时间,然后最终检查出并运行git merge
上的另一个。这种更加混乱的工作流程导致对合并过程的输入更加复杂,正如我上面提到的那样,它实际上由三个提交组成。
在这三个提交中,您仅选择了两个。第三个,Git自动为您选择。
让我们花点时间回顾一下使用图纸创建新提交的过程。您:
git checkout somebranch
<edit various files>
git add <some edited files>
git commit
checkout
步骤会填充索引(或多或少提议的下一个提交)以及工作树,其中包含位于分支{当前 tip 处的所有提交文件{1}}:
somebranch
(每个字母代表一个实际的提交哈希ID)。最新提交...--F--G--H <-- somebranch
的父级是提交H
; G
的父级是G
,依此类推,在分支上“上”(包含在其中)的提交行向下。
编辑文件时,将更改工作树副本。然后,您必须F
将那些更改复制回索引中— git add
使用索引(建议的提交,文件处于特殊的经过Git冻结的状态),而不是工作树(正常的日常文件格式,可由常规的非Git程序使用)。最后一步,git commit
,打包所有文件的索引副本,不仅是您更改过的文件,还包括其中所有 all 未更改文件的索引副本由于提交git commit
而建立索引,并将它们存储到新的提交中,并在其中冻结所有时间,以便将来任何时候都可以返回到新的提交。
我们将此新提交称为H
。 I
的父母将是I
:
H
...--F--G--H <-- somebranch
\
I
的 last 步骤是更新名称 git commit
,以使其指向提交somebranch
而不是提交I
:
H
(而且我们不再需要图形中的扭结)。
因此,在您的特定过程中,您选择的分支为...--F--G--H--I <-- somebranch
,并添加了新的提交:
master
然后您创建了一个新的分支 name 。默认情况下,这个新名称还指向提交...--F--G--H--I <-- master
。通过I
进行的提交现在位于两个分支中(包含在两个分支中):
I
现在,我们的图纸需要再添加一项。 Git如何知道在这里使用哪个分支 name ?答案是,Git在所有这样的大写字母中将特殊名称...--F--G--H--I <-- master, MyBranch
附加到分支名称之一。当HEAD
或git status
说到on branch master
时,这就是您所在的分支。假设您创建并进入on branch MyBranch
,以便拥有:
MyBranch
现在,您创建另一个新的提交。这会得到一个很大的难看的哈希ID,但我们将其称为...--F--G--H--I <-- master, MyBranch (HEAD)
。和以前一样,Git将根据索引中的内容进行新的提交,因此您可以编辑文件,J
将它们复制回索引中,然后git add
进行git commit
:< / p>
J
(请注意,...--F--G--H--I <-- master
\
J <-- MyBranch (HEAD)
仍附加到更新的分支。)
现在可以运行HEAD
了,但是这种合并不是很有趣。太琐碎了。这里永远不会有任何合并冲突。实际上,默认情况下,git checkout master; git merge Mybranch
会注意到不需要合并,而是执行快进。您必须运行git merge
来强制它进行真正的合并(该合并会很好)。
首先,让我们在git merge --no-ff
上进行一次新提交,而不是立即进行合并。实际上,只是为了使合并得到字母master
,我们在M
上进行两次提交,所以我们有:
master
现在,当我们运行 K--L <-- master (HEAD)
/
...--F--G--H--I
\
J <-- MyBranch
时,Git必须做一些实际的工作。
第一部分在于查找三个输入提交:
这三个提交之一是您当前正在执行的提交-提交git merge MyBranch
或L
或master
(两个名称,再加上原始哈希ID) ,选择该特定的提交)。该特定提交的文件将位于您的索引和工作树中,而索引或工作树中没有任何更改(HEAD
会检查这种情况,并且通常不会让您使用“脏”索引或工作树)。
这三项之一是您命名的提交:在git merge
中,您已将提交命名为git merge MyBranch
。
最后一个提交-您没有选择的提交-是Git所说的合并基础,它是共同的起点两个分支分歧。由于我们一直在绘制这些内容,因此很容易看到哪个提交:它是提交J
。
当我们从提交I
开始并向后工作时(如Git所做的那样),我们先列举提交L
,然后依次是L
,然后依次是K
和{{1} }, 等等。同时,当我们从提交I
开始并向后工作时,我们先列举提交H
,然后依次依次是J
和J
,等等。
共享提交是I
,H
,I
,H
等,但是 best 共享提交是最后,或提交G
。因此,提交F
是合并的基础。
现在I
找到了三个输入,它的主要工作开始了:
比较提交I
(或其中的快照)以提交git merge
的快照。这里有什么不同,是我们在I
上更改了我们的内容:
L
比较提交master
与提交git diff --find-renames <hash-of-I> <hash-of-L>
。这里有什么不同,是在I
上更改了他们(好,“我们”)的内容:
J
组合这两个比较的结果。
将合并的更改应用于提交MyBranch
中的快照。
如果一切顺利,则合并的更改(将快照从git diff --find-renames <hash-of-I> <hash-of-J>
捕获到I
的那些,加上将快照从I
捕获到L
的那些,现在已合并在每个文件的索引副本和工作树副本中,I
提交结果,就像通过J
一样,但进行的提交同时记住两者 {{1} } 和 git merge
:
git commit
并没有直接记录合并使用的提交L
的事实,但这是隐含的:提交J
和 K--L
/ \
...--F--G--H--I M <-- master (HEAD)
\ ___/
J <-- MyBranch
的合并基础为I
,并且始终会永远都是这样,因为任何提交中的每一个信息都一直冻结。例如,事实是L
的父母是J
,而I
的父母是L
:这些事实不能更改。 K
的父母现在分别为K
和I
,无法更改。任何提交的任何部分都永远无法更改:至多,我们可以做出新的和改进的(和不同的)提交,只是停止使用旧的提交,但是我们不能更改旧的提交。>
不进展顺利时,您会遇到合并冲突。例如,如果从M
到L
的差异表示要将文件J
的第10行从I
更改为J
,而差异从{{1 }}到test.txt
表示要将文件ABC
的第10行从XYZ
更改为I
,这些更改会发生冲突。 Git将:
合并没有结束,但也没有完成。现在,合并未完成的事实记录在两个地方:
L
的哈希ID的文件中,以便最终的合并“进行提交”步骤知道要包含哪个哈希ID作为另一个父ID。 (第一个父级test.txt
哈希ID始终可以通过ABC
获得。)您的工作将变为:为此文件生成正确的组合,并将其写入staging-slot-zero处的索引中,以声明该文件已解决。 AEIOU
命令将处理第二部分(写索引),但是您必须自己提出正确的 content 或借助合并工具
解决所有冲突后,请运行:
J
或:
L
在这种情况下两者都做相同的事情:HEAD
确保有一个正在进行的合并可以完成,如果是这样,实际上只是运行git add
(无论如何,现在-适用于Windows的Git用户一直将一个命令粘贴在另一个命令中,而不是运行另一个命令,因为Windows显然要花几个小时…...好吗,十分之几秒?...才能将一个命令链接到另一个命令,而不是Linux上的微秒)。