从中央回购中拉出git-subtree冲突

use*_*951 13 git git-subtree

我有几个依赖于同一个库的项目,为此我想维护一个单独的git存储库,以便在每个项目中使用git-subtree进行管理.例如,在每个项目中,我可以做到:

project1$  git subtree add --prefix=lib1 /path/to/lib1.git master
project2$  git subtree add --prefix=lib1 /path/to/lib1.git master
Run Code Online (Sandbox Code Playgroud)

现在在处理project1的过程中,我对lib1进行了一些更改,比如lib1/file1.c,并将其推回到中央仓库:

project1$  git add lib1/file1.c
project1$  git commit -m "updates to lib1"
project1$  git subtree push --prefix=lib1 /path/to/lib1.git master
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.但现在我想更新project2的lib1副本.所以我尝试:

project2$  git subtree pull --prefix=lib1 /path/to/lib1.git master
Auto-merging lib1/file1.c
CONFLICT (content): Merge conflict in lib1/file1.c
Automatic merge failed; fix conflicts and then commit the result.
Run Code Online (Sandbox Code Playgroud)

这是怎么回事?我确定没有对project2下的任何lib1文件进行任何更改,那么为什么会出现冲突呢?

冲突是半空的,就像这个问题中报道的那样.所有东西都在一个系统(OS X)中被拉/推,所以我知道那里的线路结尾没有问题.

当然这是git-subtree的常见用例,并且有一个我看不到的简单答案.请帮忙!

编辑:我发现了一个令人不满意的解决方法:在将更改推送到子树后,我需要重新运行子树拉:

project1$  git subtree push --prefix=lib1 /path/to/lib1.git master
project1$  git subtree pull --prefix=lib1 /path/to/lib1.git master
Run Code Online (Sandbox Code Playgroud)

即使没有变化,它也会找到一些东西,并进行合并提交.然后,在其他地方做了一些改变之后,第二次从中央仓库撤出时就不会发生冲突.但是如果我在推动后忘记立即拉动,那么下一次拉动就会发生这种冲突.

所以现在我的问题是,为什么这有效?git-subtree跟踪推送的方式是否有错误,或者我错过了什么?

dre*_*eid 5

我实际上通过一些试验和错误找到了正确的方法.

执行此命令后:

project1$  git subtree push --prefix=lib1 /path/to/lib1.git master
Run Code Online (Sandbox Code Playgroud)

执行获取命令:

project2$  git fetch /path/to/lib1.git master
Run Code Online (Sandbox Code Playgroud)

然后做你的拉:

project2$  git subtree pull --prefix=lib1 /path/to/lib1.git master
Run Code Online (Sandbox Code Playgroud)

  • 这必须是公认的答案。正是我所需要的。 (2认同)

ape*_*arr 5

不幸的是,如果不给新拆分的提交提供完全不同的提交 ID,就没有好的方法可以将提交从树中分离出来。这是因为它们毕竟是不同的提交:它们不包含不在子树中的部分。这意味着当您将它们拉回时,git 会将它们视为全新的提交并产生冲突。

你可以做两件事。其他答案之一建议在您推送后立即执行 git subtree pull。这会起作用,但你最终会得到每个提交的两个副本,因为从技术上讲确实有两组更改:上游更改(由 git-subtree push/split 自动生成)和组合项目中的更改,并且您是将它们合并在一起。此方法的快捷方式是--rejoin拆分/推送选项,这会立即添加额外的合并提交。

第二种选择是使用--squash. 这也会创建新的合并提交,但是由于您将上游存储库中的所有更改合并为单个提交而不是每个原始提交一个,因此它会减少历史记录中的混乱。大多数人似乎更喜欢--squash.


小智 3

好吧,这似乎是 git-subtree 中的一个错误。我根据自己的需求评估了它并放弃了。基本上,git-subtree推送会改变提交消息,因此提交的SHA1会发生变化。您必须拉取以合并其他提交,这些提交引入了完全相同的更改,但由于更改的提交消息而具有不同的 SHA1 哈希值。GIT 正确处理双重合并(再次合并相同的更改),因此它默默地记录合并。

必须有人来解决它!

  • 这解释了为什么推拉式的工作原理如此,谢谢。令人沮丧的是子树无法自动处理如此简单的场景。是否有其他方法可以避免更改 SHA1 进行推送,或者我们是否回到使用子模块? (3认同)