合并冲突
有时,在合并或从分支拉取时,您会遇到“合并冲突”。然后 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的屏幕截图:
