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

时间:2013-06-21 18:31:15

标签: 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

现在在处理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

到目前为止,这么好。但现在我想更新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.

发生了什么事?我确信没有对project2下的任何lib1文件进行任何更改,那么为什么会出现冲突呢?

冲突是半空的,就像this question中报道的那样。所有东西都在一个系统(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

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

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

4 个答案:

答案 0 :(得分:5)

我实际上通过一些反复试验找到了正确的方法。

执行此命令后:

project1$  git subtree push --prefix=lib1 /path/to/lib1.git master

执行获取命令:

project2$  git fetch /path/to/lib1.git master

然后做你的拉动:

project2$  git subtree pull --prefix=lib1 /path/to/lib1.git master

答案 1 :(得分:4)

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

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

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

答案 2 :(得分:2)

好吧,它似乎是git-subtree中的一个bug。我根据自己的需要对其进行了评估 放弃。 Basicaly,git-subtree push改变提交消息,因此提交的SHA1更改。您必须提取合并其他提交,这些提交引入了完全相同的更改,但由于更改了提交消息,因此只有不同的SHA1哈希值。 GIT正确处理双重合并(再次合并相同的更改),因此它会默默地记录合并。

有人必须解决它!

答案 3 :(得分:1)

在主项目中,尝试始终使用squash命令进行拉动和推送:

第1步:使用壁球拉下子树

 git subtree pull --prefix=mainProjectFolder/subtreeFolder http://bitbucket.org/repo.git master --squash

第2步:使用壁球推送子树

 git subtree push --prefix=mainProjectFolder/subtreeFolder http://bitbucket.org/repo.git master --squash

squash标志将避免为不同存储库中的相同提交创建新的SHA1 id。

解释: 为了解决这个问题,您可以在推送和拉动子树时使用壁球标志。 @Borg描述的关于SHA1提交id的问题是正确的,但是子树并没有真正为此构建。你应该避免保留提交ID'父项目和子项目中的子树(库)存储库。如果您将更改从父存储库推送到子树存储库,请遵循文档中的此语句(第58行):That is, if you make a change that affects both the library and the main application, commit it in two pieces.

video解释了不使用子树时的问题。如果出现以下情况,请直接拖到11:00分钟,以发现子树不适合您:

  

您可以不断更新存储库,

     

或者,如果您有很多依赖项,

     

或者,如果团队中的每个人都必须学习子树。