首页 > 解决方案 > 无法解决与 git 子模块文件夹的合并冲突

问题描述

我有两个 git 分支,需要合并开发和重新设计。我有一个名为 library 的子模块,develop 正在跟踪它的更新。当我运行 ' git merge' 时,它说库已被两者修改,即使我没有触及库子模块。当我单击 VS Code 中的库以查看冲突更改时,我看到:

diff --cc library
index 749618f9,589a7ae5..00000000
--- a/library
+++ b/library

git submodule update在合并之前,我尝试在重新设计分支中删除库文件夹并运行“ ”,但没有成功。我在重新设计时将 ignore = all 添加到 .gitmodules 文件中,但没有用。如何摆脱与此子模块的合并冲突?

标签: gitgit-mergegit-submodulesgit-merge-conflict

解决方案


问题在于,关于合并基础提交,这两个分支library 都已被修改。这里的诀窍是理解“修改”子模块意味着什么。

请记住,任何子模块的本质是您的超级项目正在引用其他 Git 存储库。另一个 Git 存储库——被用作模块的那个——不知道它被用作子模块。它只是一个普通的旧 Git 存储库。1 它有提交。任何一次提交的真实名称都是其哈希 ID。使用这个子模块的超级项目在模块中运行 Git 命令,通过哈希 ID告诉它git checkout某个特定的提交,这导致子模块 Git 处于分离的 HEAD模式。

同时,回到超级项目:这个仓库是一个普通的 Git 仓库。它有提交。每个提交的真实名称是一些哈希 ID,但通常您会使用git checkout一些分支名称。分支名称将解析为某个特定的哈希 ID,并且您的超级项目 Git 将通过该分支名称检查该提交——例如,develop——并且现在处于某个特定的提交上,例如,a123456.... 所以假设你在 commit a123456

commit的某个地方a123456,有一个类似文件的对象,它实际上不是一个文件,而是一个gitlink。提交中的这个 gitlink 对象包含子模块中存在的某些提交的原始哈希 ID。在您的情况下,此 gitlink 是名称的条目,library它包含,例如589a7ae5. 那是子模块的提交:如果你运行,你的超级项目 Git 将git submodule update输入子模块 Git 并命令它到git checkout 589a7ae5.

所以:超级项目中的每个提交都有一个名为“文件” library,它实际上是一个 gitlink,并且存储了一些哈希 ID。您现在已经运行:

git checkout develop
git merge redesign

(或者反之亦然)。该git merge命令已找到由分支名称develop和指定的提交,以及作为其他两个提交的合并基础redesign的第三个提交。

所有这三个提交都有(或缺少:你的一个是00000000)一个名为 .gitlink 的 gitlink 条目library。这些 gitlink 中的三个哈希 ID 都是不同的。Git 现在正在尝试合并两个差异:

  • 一个差异说从合并库中的 gitlink X 开始,用哈希 ID Y 替换那个 gitlink
  • 另一个差异表示从合并基础中的 X 开始,将其替换为 Z

这两个指令——用 Y 代替,用 Z 代替——相互冲突。Git 不知道哪一个是正确的(如果事实上任何一个都是正确的)。

为了解决这个特定的合并冲突,您的工作是为子模块选择正确的哈希 ID。一旦你知道了正确的哈希 ID——<em>如何找到这取决于你2——你只需暂时更改到子模块 Git 存储库并运行,然后返回超级项目并运行。您的超级项目 Git 现在在 gitlink 中记录了新的哈希 ID,它将进入合并提交,并且合并冲突已解决。git checkout hashgit add library

当您解决了所有合并冲突(包括普通文件冲突(如果有))并准备好提交合并、运行git merge --continuegit commit完成合并时。合并提交将具有您添加的哈希 ID作为gitlink for 。library

(如果正确的做法是完全停止使用子模块,您可以git rm library先检查正确的子模块哈希,然后再git add输入名称。)


1这会跳过一些技术细节,通过这些细节可以发现这个子模块存储库存在于某个超级项目中。重要的是,大多数 Git 完全没有意识到这些细节:子模块认为它是独立的,就像它本来的样子。此外,一个典型的子模块 Git 存储库是其他 Git 存储库的克隆,而其他Git 存储库完全不知道克隆,所以即使克隆(您正在使用的子模块)知道它是一个子模块,它的 origin仍然不会意识到。

2查找正确哈希 ID 的典型示例方法如下:

cd library

后面是各种git log和/或git show和/或git checkout命令,或者可能gitk --all是你喜欢用来查看 Git 存储库的任何东西。最终,您会发现一些看起来不错的哈希 ID 并git checkout在其上运行,以便更新此存储库中的工作树,然后cd退出子模块并构建和测试项目。这个过程自然而然地将子模块留在正确的提交上,这样您就不必重新git checkout设置正确的哈希 ID。


推荐阅读