Git 子树、子模块 - 在另一个项目中处理一个项目

Git subtree, submodules - working with a project inside another one

我正在尝试弄清楚如何使用 git 子树(据我所见,子模块不是我想要的)以便同时处理两个 git 存储库一个项目在另一个项目中的时间。

就我而言,我在主存储库中使用 Unity。我决定将我的一些代码作为一个包,所以我在文件夹 repositoryRoot/Packages/com.mypackage 中有另一个 git 存储库,所以我可以在我未来的项目中使用这个包。

我不明白我应该使用哪些命令和 git 功能来分别提交到两个存储库,我猜,只将对包的更改提交到包的存储库,并且也不是主要项目(或者我应该?)。

首先,值得注意的是 git subtree 是 Git 世界中的一种 red-headed stepchild。过于依赖它可能是不明智的。

除此之外,子树和子模块之间存在巨大差异:

  • A Git 子模块 只是采用一些现有的 Git 存储库并 使用它的情况 来自其他 Git 存储库。为此,我们称之为 超级项目 的用户只需列出路径名和 URL 其中 Git 应该 运行 a git clone 克隆 use-ee,或 子模块 。此清单进入 .gitmodules 文件,由 git submodule 命令维护。克隆后,超级项目偶尔会 cd 进入子模块和 运行 git checkout --detach <em>hash</em>,其中要使用的 哈希 ID 存储在 您在超级项目 中所做的每个提交中。这些被称为 gitlinks 并且 always 导致分离的 HEAD。

    这样做的结果是,当您在超级项目中工作时,您不会在子模块中做任何工作:超级项目只是调用一些提交已经存在在该子模块中。如果您需要的提交不存在,您需要做的是找到或创建子模块存储库的克隆,在那里工作,创建您需要的提交,确保一切正常,将其推回您的超级项目所在的位置将从中克隆以便 每个人 都存在提交,然后才进行新提交 引用此新子模块提交的超级项目通过已更新 gitlink.

    你工作的克隆,当你必须提交一个新的子模块时,可以远离超级项目及其子模块,或者你可以只是使用您已经拥有的克隆。请记住,超级项目 Git 将在某个时候深入到子模块 Git 并进行分离头检查。 (如果你当时正在 子模块中工作,那可能会把你的工作搞砸,所以要确保这不会发生——也就是说,不要让任何人 运行 任何 Git 命令 超级项目中——或者使用不同的克隆,或者添加的工作树,或者其他东西。如何并不重要 你确保超级项目 Git 不会把你搞砸,只是你 确保。)

  • A subtree,但是,被设计成,或具有可重复的“从更大的,包含, 外部 Git 存储库”进程。

使这个过程可重复有点棘手,但 可能的,前提是满足某些限制条件。特别是,我们知道 任何给定提交 的提交哈希 ID 绝对 100% 由该提交的完整内容控制,包括提交导致该提交的历史记录中的哈希 ID。只要提交的内容不改变,任何未来哈希ID的计算将完全匹配过去哈希ID的计算同样的内容。

这意味着如果更大的存储库(“supertree”?我们需要为此命名:我们就称它为 R)只有 添加了新的提交,我们对每个现有的提交应用了一个过滤函数,过滤了一些以前的副本R 将产生一些新的子树输出 S0。现在在 R 上重复相同的过程,添加新的提交,将产生一个超集 S1。这个超集将包含 S0 的所有相同提交,加上过滤新 结果的任何新提交R 提交。由于那些仅 添加到 以提交 R,新的 S 仅提交 添加 S

为了完成这项工作,R 中的任何提交都不能重新设置基址或以其他方式丢弃。 这样做会破坏我们漂亮的超集 属性 对于 S.

但是:我们可以添加 new 提交到一些提取的 Si,然后导入那些提交回R?答案是有条件的。我们必须知道,或找出,哪些提交实际上是这个 S 中的新提交,然后我们必须确保是否以及何时将它们添加到 R,我们这样做的方式是,在过滤时,我们在 期间 期间放入其中的任何内容都会“过滤掉”。这可能很棘手:我们必须保留除 tree 对象之外的所有元数据。

如果出于任何原因有必要更改此元数据,我们剩下的选择是考虑这个特定的 Si 它自己的红色可以说是有头的继子。我们导入新的提交,然后声明 Sipersona non grata 并生成替换 Si+1 并丢弃所有对 Si[=139= 的使用].

在实践中,这些规则 可以 工作,并且 git subtree splitgit subtree merge 可以处理过滤(创建一些 S) 和更新的反向导入。但是这些可能出错的小陷阱确实存在,并且 git subtree 在 Git 邮件列表中没有得到太多关注。子模块的东西得到了更多的维护。它通常更烦人,并且有其自身的尖锐边缘,但它绝对得到了更好的支持。