15

我有几个项目依赖于同一个库,我想为此维护一个单独的 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文件进行任何更改,那么为什么这里会有冲突呢?

冲突是半空的,就像在这个问题中报告的那样。一切都在单个系统(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

即使没有更改,它也会找到一些东西,并进行合并提交。然后,在其他地方进行了一些更改之后,当我第二次从中央仓库拉出时,冲突就不会发生了。但是如果我在 push 后忘记立即运行 pull,下一次 pull 就会出现这个冲突。

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

4

4 回答 4

7

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

在此命令之后:

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
于 2014-02-03T18:22:36.667 回答
5

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

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

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

于 2014-02-03T18:53:49.737 回答
3

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

必须有人修复它!

于 2013-06-25T20:36:11.897 回答
1

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

第 1 步:用壁球拉取子树

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

第 2 步:使用 squash 推送子树

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

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

说明:要解决此问题,您可以将在推拉子树时使用壁球标志作为惯例。@Borg 描述的关于 SHA1 提交 id 的问题是正确的,但子树并没有真正为此构建。您应该避免在父项目和子树项目中保留子树(库)存储库的提交 ID。如果您将更改从父存储库推送到子树存储库,请遵循文档中的以下语句(第 58 行):也就是说,如果您进行的更改会影响库和主应用程序,请分两部分提交。

视频还 解释了何时不使用子树。直接拖动到 11:00 分钟以发现子树不是适合您的解决方案,如果:

您不断更新存储库,

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

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

于 2016-07-13T00:42:24.623 回答