是否有任何git merge-strategies用于忽略提交或分支合并到目标分支的子模块更新?

时间:2015-06-23 05:01:59

标签: git github merge git-submodules merge-strategy

我的用例是: 我有一个包含子模块的repo的两个分支。 我想设置这两个分支的自动集成。但是,只要两个分支上都有子模块更新,我的自动集成脚本就会因子模块上的冲突而失败。有没有办法让git忽略合并期间子模块指针的变化? 或者为给定的子模块提供类似merge=ours的内容?

我已经阅读了 here.

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

submodule-name merge=ours

2 个答案:

答案 0 :(得分:2)

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

<块引用>

如果子模块历史已经发生分歧并且致力于在超级项目中分歧分支,[...] Git 不会为你尝试甚至是微不足道的合并。

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

假设您在 master 上并且想要将 my_branch 合并到其中。有 3 种情况:

git merge my_branch

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

git merge -Xours my_branch

我不知道这是否是解决此问题的正确方法,但是有一个非常简单的快捷方式可以清除子模块上的任何冲突。因为 git 不对子模块版本做任何合并操作,它只告诉你不同的版本。因此,如果您查看索引,您仍然会发现来自 3 路合并的 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 的那个感兴趣。不幸的是,我认为您不能引用具有公共 :2:./submodadd 的子模块修订版将其添加到索引中,因为它不是真正的路径。我告诉过你的最简单的捷径就是这个 :)

git add submod

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

git merge -Xtheirs my_branch

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

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

add

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

检索它
submod

最后,这是为了保持子模块的 git rev-parse :3:./submod 版本而运行的命令:

theirs

相反,要保留 git update-index --cacheinfo 160000,$(git rev-parse :3:./submod),submod 版本,请将 ours 替换为 :3:

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

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

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

以我的拙见,git 团队应该添加一个选项,让我们能够更好地控制如何处理这些情况。顺便说一下,您始终可以允许提交然后 theirs,或者在提交之前使用 --amend 修复它。在这两种情况下,您都不能使用索引修订版(如 git merge --no-commit),但在第一种情况下使用 :2:./submodHEAD^1,在第二种情况下使用 HEAD^2。如果这是一个非常不可能的场景,请跳过它,否则我会提交并MERGE_HEAD(如果可以接受)。

结论

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

答案 1 :(得分:0)

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

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

试试这个方法,如果对你也有帮助。

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

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