如何处理与git子模块的冲突?


127

我有一个git超级项目,它引用了几个子模块,并且我试图锁定工作流,以便其余的项目成员都能在其中工作。

对于这个问题,可以说我的超级项目被调用supery,子模块被调用subby。(然后简化了我要做的事情……我实际上并没有在版本中使用分支,但是我认为这是最容易提出问题的方法。)

我的master分支将git项目supery的标签称为子模块。的分支叫,改变了子模块的参考点来标记的。v1.0subbysuperyone.onev1.1subby

我可以轻松地在每个分支中工作,但是如果尝试使用one.one分支中的更改来更新分支,则会master收到一些冲突,并且我不知道如何解决它们。

基本上git pull . master,在subby分支中运行了一段时间之后,看起来好像创建了其他子模块。

在拉/合并之前,我git submoduleone.one分支获得了所需的响应:

$ git checkout master
$ git submodule
qw3rty...321e subby (v1.0)
$ git checkout one.one
$ git submodule
asdfgh...456d subby (v1.1)

但是在拉动之后,当我运行时,它将添加其他子模块git submodule

$ git pull . master
Auto-merged schema
CONFLICT (submodule): Merge conflict in subby - needs qu3rty...321e
Automatic merge failed; fix conflicts and then commit the results.

$ git submodule
qw3rty...321e subby (v1.0)
asdfgh...456d subby (v1.1)
zxcvbn...7890 subby (v1.1~1)

如何删除/忽略不需要的子模块引用并提交冲突和更改?还是可以与原始参数一起使用的参数git pull将忽略子模块?

Answers:


23

我之前没有看到过确切的错误。但是我对您遇到的麻烦有一个猜测。它看起来像是因为的masterone.one分支supery包含subby子模块的不同ref ,当您合并mastergit中的更改时,它不知道的分支应保留并跟踪哪个ref- v1.0v1.1- 。one.onesupery

如果是这种情况,那么您需要选择所需的引用并提交更改以解决冲突。这正是您使用reset命令执行的操作。

在项目的不同分支中跟踪子模块的不同版本是一个棘手的方面。但是子模块ref与项目的任何其他组件一样。如果两个不同的分支在连续合并后继续跟踪相同的子模块ref,则git应该能够确定模式,而不会在以后的合并中引起合并冲突。另一方面,如果switch子模块频繁引用,则可能不得不忍受很多冲突解决方案。


1
感谢您阐明这个问题。这对我来说已经很有意义了,并且reset命令对于上述情况非常适用。但是,从master分支接受子模块ref并将该ref扔给当前分支的子模块的命令是什么?我知道如何处理正常的冲突,但是经过三天的网上搜索,除了rm -r之外,我找不到任何代码示例。我开始认为这些示例不存在是有原因的;到目前为止,子模块已从超级项目中抽象出来,您必须管理每个转换。
泰勒

26
最后!一个答案!我曾added by us: ../Mono.Cecilgit statusgit addgit rm失败的Mono.Cecil: needs merge, pathspec 'Mono.Cecil/' did not match any files,因为它只是一个空文件夹和git只有真正手柄文件。git checkout给了我Mono.Cecil: needs merge, error: you need to resolve your current index firstgit submodule update给了Skipping unmerged submodule Mono.Cecilgit checkout master Mono.Cecil最后固定它。基本问题:git status建议是错误的,因此请选择一个分支并使用来获取其文件夹副本checkout
IBBoard 2012年

6
@ IBBoard的命令帮助我这样的情况-我想git checkout --ours SUBMODgit add SUBMOD等人,但最后做着git checkout master SUBMOD固定的冲突。此评论可能应该是答案,而不是评论... :)
Colin D Bennett

89

好吧,它在技术上与子模块之间的冲突没有得到管理(即:保留此问题,但不保留此冲突),但是我找到了一种继续工作的方法……而我要做的就是注意我的git status输出并重置子模块:

git reset HEAD subby
git commit

这会将子模块重置为拉前提交。在这种情况下,这正是我想要的。在其他需要将更改应用于子模块的情况下,我将使用标准子模块工作流程(签出母版,下拉所需的标签等)来处理这些更改。


对我来说,这似乎只会将冲突模块的状态从“两个已修改”更改为“已删除”。
Matt Zukowski

4
您可能要保留合并分支的子模块:git reset <merged-branch>子作者
Edward Anderson

1
按照答案中的规定为我工作.. git reset HEAD path / to / submodule / dir
estoy

56

我在这个问题上的答案有点挣扎,并且在类似的SO帖子中也没有太多的运气。所以这对我有用-记住在我的情况下,子模块是由另一个团队维护的,因此冲突来自master和我正在处理的项目的本地分支中的不同子模块版本:

  1. 运行git status-记下冲突的子模块文件夹
  2. 将子模块重置为当前分支中最后提交的版本:

    git reset HEAD path/to/submodule

  3. 至此,您已经有了子模块的无冲突版本,现在可以将其更新为子模块存储库中的最新版本:

    cd路径/到/子模块
    git子模块foreach git pull origin SUBMODULE-BRANCH-NAME
  4. 现在您可以commit做到并重新开始工作。


16

首先,找到您想要子模块引用的哈希。然后跑

~/supery/subby $ git co hashpointerhere
~/supery/subby $ cd ../
~/supery $ git add subby
~/supery $ git commit -m 'updated subby reference'

这对我来说很有效,可以使我的子模块获得正确的哈希引用,并继续我的工作,而不会遇到任何进一步的冲突。


1
或者你可以只是做一个git结帐--theirs(或--ours)subby
八尺

@Bachi:git checkout --theirs和--ours对子模块没有影响。
爱德华·安德森

1
尽管这确实解决了冲突,但确定<hashpointerhere>并不容易。我不知道一种简单的方法来查看冲突每一侧的子模块提交。无论您在subby中签出的任何提交都可能与合并的任何一方不同,这不适用于合并提交。
爱德华·安德森

@nilbus是真的。我们已经放弃了使用git子模块,因为这是我们所关心的问题之一,因此很难确定您真正想要的提交。我们使用composer(php)作为程序包管理器,我实际上很喜欢它,因为它创建了一个将文件库锁定到特定哈希值的锁定文件。但是,由于我们在多个存储库中使用了node_modules,因此我们会在这里和那里遇到冲突的模块。从那以后,我们已切换到npm来管理这些东西,但这也完全是其他蠕虫病毒。
hellatan

12

我在git rebase -i origin/master分支机构遇到了这个问题。我想获取子模块ref的主版本,所以我只是做了:

git reset master path/to/submodule

然后

git rebase --continue

那为我解决了问题。


3
这对我有用。我仍在弄清楚他们为损坏子模块
所做

3

从此讨论中获得了帮助。就我而言

git reset HEAD subby
git commit

为我工作:)


2

好吧,在我的父目录中,我看到:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Unmerged paths:
(use "git reset HEAD <file>..." to unstage)
(use "git add <file>..." to mark resolution)

所以我只是这样做

git reset HEAD linux
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.