我知道编辑这个网站吗?

Git 冲突

合并冲突

有时,在合并或从分支拉取时,您会遇到“合并冲突”。然后 Git 会告诉你类似的信息

CONFLICT (content): Merge conflict in Fakefile

它还告诉您解决冲突然后提交结果。那么如何解决冲突呢?

解决合并冲突

首先了解一些背景知识:什么是合并冲突,它是如何发生的?当当前分支和要合并到当前分支的分支出现分歧时,通常会发生合并冲突。也就是说,您当前分支中的提交不在其他分支中,反之亦然。

通常,有一个分支点,即最新的公共提交。这是基本提交。

现在,当 Git 将另一个分支合并到当前分支时,它会查看基本提交和当前修订版本之间的差异,以及基本提交和另一个分支的最新提交之间的差异。当存在明确差异时(即只有一方更改了某段代码),则会应用更改。

当存在不一致的更改时,就会发生合并冲突。在这种情况下,您的冲突文件将具有所谓的“冲突标记”:

<<<<<<< HEAD
my version
=======
the other version
>>>>>>> deadbeef... This is the tip of the other branch

«««<======= 之间,您将根据当前分支中相对于基本提交的更改找到版本。

========»»»» 之间,您将根据另一个分支找到相对于基本提交的版本。

为了方便起见,在 «««<»»»> 标记之后,您将看到有关冲突的该部分源自哪个提交的提示,HEAD 当然是当前修订版。

要解决冲突,您必须决定最终结果应该是什么。这不是你不假思索就能做的事情,否则 Git 会帮你做的。

例如,.gitignore 中的合并冲突通常通过同时采用当前版本和其他版本来解决:

<<<<<<< HEAD
jars/VIB-lib.jar
=======
plugins/Gabriels_Plugin.jar
>>>>>>> badcoffe... Add a new plugin to take over the world

可以解析为

jars/VIB-lib.jar
plugins/Gabriels_Plugin.jar

但要注意:如果行被_removed_,您将不得不以不同的方式解决。例如,

<<<<<<< HEAD
jars/Blub.jar
jars/some-lib.jar
=======
plugins/Blub.jar
>>>>>>> abba123... Move Blub.jar to plugins/

可能想要解决

jars/some-lib.jar
plugins/Blub.jar

所以你一定要仔细考虑一下这个决定!

子模块冲突

上一节讨论了文件冲突。当然,不同的子模块版本之间也可能发生冲突。示例(子模块 ImageJA):

Auto-merging ImageJA
CONFLICT (submodule): Merge conflict in ImageJA

由于超级项目中子模块的“内容”是子模块的当前提交名称,因此 diff 将向您显示如下内容:

diff --cc ImageJA
index 6335c9b,d245d31..0000000
--- a/ImageJA
+++ b/ImageJA
@@@ -1,1 -1,1 +1,1 @@@
- Subproject commit 6335c9b0b39aa96001b5f9be665aabe3c854bae6
 -Subproject commit d245d31d53e1f85264113c99609b8379eaee38ee
++Subproject commit 7bbce1e02aa3ba1971533441e9a50c75764c8e92

要解决此问题,您可以将其中一项提交设为子模块中的当前提交,然后 git add 超级项目中的子模块。或者您可以立即在超级项目中使用 git checkout

git checkout --theirs ImageJA

或您的版本:

git checkout --ours ImageJA

提交决议

解决所有冲突后(如果有疑问,冲突在哪里,只需调用 git diff),添加已解决的文件内容:

git add <file>

然后提交合并:

git commit -s

使用外部合并工具

对于复杂的冲突,您可能会发现使用外部合并工具更容易解决,该工具可以并排显示文件的三个版本。您可以通过以下方式执行此操作:

git mergetool

…这将为您提供多种工具选择。这是使用git mergetool --tool=meld的屏幕截图:

meld-example