11

我的用例是:我有一个包含子模块的仓库的两个分支。我想设置这两个分支的自动集成。但是,每当两个分支上都有子模块更新时,我的自动集成脚本就会失败,并且子模块会发生冲突。有没有办法让 git 在合并期间忽略子模块指针的变化?或者为merge=ours给定的子模块提供类似的东西?

我在这里读过这个

我在上面的页面中为这样的子模块文件夹尝试了合并策略(但它只适用于文件)

submodule-name merge=ours
4

2 回答 2

3

老实说,我也很惊讶,但文档很快解释了发生了什么:

如果子模块的历史已经分道扬镳,并致力于在一个超级项目中分叉分支,[...] Git 不会为您尝试哪怕是微不足道的合并。

我猜“为什么合并策略不起作用? ”这个问题的答案是:因为不同子模块版本之间没有合并过程。如果您需要进行实际合并,则文档建议的方法仍然不是那么复杂,但在您的情况下它甚至“更容易”。

假设你在master并且你想合并my_branch它。有3种情况:

git merge my_branch

我已经链接的文档很好地解释了这一点,所以我没有理由重复它。我仍然建议您阅读它,因为您可能会遇到意想不到的情况。我在答案的最后告诉你。

git merge -Xours my_branch

我不知道这是否是解决此问题的正确方法,但是有一个非常简单的快捷方式可以清除子模块上的任何冲突。因为 git 不对子模块版本做任何合并操作,它只会告诉你不同的版本。因此,如果您查看索引,您仍然会发现来自 3-way 合并的 3 个版本

(的输出git ls-files -s

100644 acbc19aafbf0c14e67f9a437d465351a7e96388b 0   .gitmodules
100644 3da4fcc7b3a9bc886b50977dc35e10f48a42416b 0   your_files
160000 e826e1b762a17dbc7225b36db4a9f7f6c08774ad 1   submod
160000 fef2abfb901d20ba1f4d1023ba384bbc6afbc392 2   submod
160000 cd5caa8674fe078e0fb875861bb075ccb60cfee0 3   submod

第一个(e826e1b)是合并基础,但您对索引为 2 的那个感兴趣。不幸的是,我认为您不能在将其添加到索引时引用带有 common 的子模块修订,:2:./submod因为add它不是真正的路径。我告诉你的最简单的捷径就是这个:)

git add submod

然后你就可以了commit。它会自动保留master子模块版本,但这当然不是最好的方法,因为行为可能会在 git 的某些未来版本中发生变化。我将向您展示下一个场景的另一种方式。

git merge -Xtheirs my_branch

这里事情变得复杂了:我们不能使用上面的技巧(简单add,现在默认为master子模块修订版),因为现在我们需要索引为 3 的修订版,这:3:./submod不适用于add命令。

您还可以使用管道命令更新索引update-index并传递原始缓存信息条目,例如:

git update-index --cacheinfo 160000,cd5caa8674fe078e0fb875861bb075ccb60cfee0,submod

mode160000是用于子模块的模式(更具体地说是用于 git 链接),cd5caa86...是我们要添加到索引中的对象,submod也是路径。奇怪的是,在这里放置子模块名称是可行的。如果你需要编写脚本,你显然不能在那里放置一个硬编码对象,但你可以用它来检索它

git rev-parse :3:./submod

最后,这是运行以保持theirs子模块版本的命令:

git update-index --cacheinfo 160000,$(git rev-parse :3:./submod),submod

相反,要保留ours版本,请替换:3::2:.

Git 不会合并子模块,但可以重用合并

这部分在参考资料中也得到了很好的解释,但你需要非常小心。总之,git 不会尝试合并您的子模块,除非:

  • 合并可以使用快进策略解决,在这种情况下,它使用最近的提交,或者
  • 冲突子模块修订的合并已经在子模块存储库中,因此 git 只会将该合并提交添加到索引(而不是oursor theirs)。

在我看来,git 团队应该添加一个选项,让我们更多地控制我们想要如何处理这些情况。顺便说一句,您总是可以先允许提交,然后再提交--amend,或者在提交之前使用git merge --no-commit. 在这两种情况下,您都不能使用索引修订(如:2:./submod),但在第一种情况下和HEAD^1在第二种情况下使用。如果这是一个非常不可能的情况,请跳过它,否则我会提交并且如果它是可以接受的。HEAD^2MERGE_HEAD--amend

结论

我希望有一种更简单的方法可以将具有不同子模块修订的分支合并,因此不要将此答案视为唯一的可能性。此外,在合并之后,您可能需要deinit重新初始化(或重新sync)您的子模块,但只要这是可编写脚本的,这不是一个真正的问题。如果我是你,我会创建一个包含所有这些操作的别名。

于 2021-03-26T12:52:01.740 回答
0

即使这是一个旧帖子,只是为像我这样的懒人发表评论:P

基本上,如果您的子模块历史记录与您要合并的分支不同,您就会遇到此问题。

试试这种方式,如果也可以帮助你。

  1. 使用您想要的分支更新(或合并)您的子模块分支。
  2. 在主模块中提交并推送子模块的所有更新引用。
  3. 现在尝试合并,它应该可以工作。

由于子模块历史记录不匹配,请尝试通过拉/恢复/转移到其他分支来匹配它们并提交这些子模块引用,这对我有用。希望它也适合你。

于 2021-07-07T08:56:44.490 回答