SZT*_*SZT 2 git git-submodules
我有三个存储库。
RepoCommon作为子模块添加到RepoTn和RepoTh。和RepoTn都是RepoTh两个不同的存储库,因为在开发早期就认识到这两个是独立的应用程序。但现在后来在开发部分我们意识到RepoTn是高度依赖的RepoTh。
作为一个解决方案,我正在考虑将其RepoTh作为子模块添加到RepoTn. 但令我困扰的一件事是RepoCommon里面的“额外” RepoTh。如果我这样做,它基本上将具有以下结构:
我想知道当我想将RepoCommon其RepoTh作为子模块添加到RepoTn.
注意:RepoTh需要继续存在,因为它也有自己独立的存储库。另外,我问这个问题的另一个原因是,如果我可以删除/忽略RepoCommon我可以修改项目文件以确保系统使用正确的RepoCommon文件夹。如果这有什么区别的话,我正在使用 Visual Studio 2019。也欢迎任何其他更好解决方案的建议。
最简洁的答案是不。这会产生一个问题,您可以通过使用长答案来解决该问题,但避免这种设置可能是明智的。请参阅VonC 的回答。
\n您必须记住这里的子模块是什么\xe2\x80\x94 但在我们到达那里之前,让我们准确定义 Git存储库是什么。对此有很多注意事项,但简而言之,Git 存储库是提交的集合。1 每个提交都有一个唯一的编号:一个丑陋的大哈希 ID,为该提交保留,遍布每个 Git。该提交用于保存 Git 在当时所知道的每个文件的快照,无论是谁进行了提交。2
\n除了这些存储的文件(Git 内部将其称为blob 对象)之外,Git 还可以保留 Git 内部称为gitlink的内容。稍后当我们讨论子模块时,我们将了解 gitlink 的确切形式。
\n一旦您通过哈希 ID 选择了某个提交\xe2\x80\x94(您可以让 Git 通过分支名称查找该提交,例如存储库中的\xe2\x80\x94),您就可以让 Git 检出该提交(使用git checkout或 ,因为Git 2.23,git switch)。这会将提交提取到一系列可用(且可修改!)的普通文件中。Git 将3 个这些文件复制到 Git 的索引中,索引是 Git 用于进行新提交的每个存储库的数据结构。4 如果提交包含任何 gitlink,Git 还会将这些 gitlink 复制到其索引中。
1最大的警告是.git存储库所在的目录实际上是两个主要数据库,加上一些辅助数据。一种从哈希 ID 映射到内部 Git 对象,其中包括提交,但还包括其他三种对象类型。第二个映射名称\xe2\x80\x94,包括分支和标签名称,这是人们在这里最常使用的\xe2\x80\x94到哈希ID ,以便例如人类可以使用第一个数据库中的哈希ID 。
当您克隆存储库时,您的 Git 按原样复制对象数据库,并使用其他 Git 的名称到哈希 ID 数据库来构建您自己的(不同的)名称到哈希 ID 数据库。\xe2\x80\x94 没有其他任何辅助数据,例如钩子、索引或像 CHERRY_PICK_HEAD\xe2\x80\x94 这样的特殊伪引用,都不会被复制。因此,对象数据库非常重要,并且由于人类使用名称数据库来定义分支\xe2\x80\x94 的概念,这与 Git 的\xe2\x80\x94 不太一样,所以第二个数据库也很重要。然而,这里我们最关心的是对象数据库。
\n2除了快照之外,还提交存储元数据,但这里我们只关心快照本身。
\n3存储的文件以特殊的、只读的、仅限 Git 的格式保存,其中文件被压缩和(重要的是)重复数据删除。进入索引的实际上是 blob 哈希 ID,因此索引“副本”根本不是真正的副本;但索引还保存文件的名称以及使 Git 运行更快的数据。
\n4索引具有其他作用,但通过保存每个文件的“副本”以及文件的路径名,索引充当下一次提交的模板。当你使用 时git add,你实际上在做的是更新 Git 的索引,这样下一次提交就不会与当前提交相同。
Git 中的子模块只是另一个 \xe2\x80\x94separate\xe2\x80\x94Git 存储库,有一个特殊的关系:子模块 Git 存储库由其他某个 Git 存储库控制。控制 Git 存储库是超级项目,受控 Git 存储库是子模块。
\n鉴于存储库的工作方式是签出提交\xe2\x80\x94,以便您拥有可以使用的文件,而不是只有 Git 本身可以使用的特殊压缩格式的文件\xe2\x80\x94超级项目 Git 本身需要做的,一旦子模块 Git 存储库克隆到位,就是git checkout 在该子模块中运行。这就是它的作用:
cd $path\ngit checkout $hash\nRun Code Online (Sandbox Code Playgroud)\n对于git checkout子模块内的某些提交,超级项目需要知道两件事:
$path?$hash?这两件事正是 gitlink 中的内容。每次提交都会存储文件。提交还可以存储 gitlink。文件或 gitlinks 被复制到超级项目 Git 的索引中。索引中的每个条目都包含路径名、哈希 ID 和一些其他内部 Git 数据。路径名和哈希 ID 正是超级项目 Git 执行上述命令所需的。
\n这就是全部内容……嗯,几乎全部。还需要一件事:超级项目 Git可能需要运行git clone,才能实际创建子模块存储库。这里超级项目Git需要的信息存储在超级项目中的.gitmodules 文件中。5然而, 一旦超级项目 Git 运行git clone,.gitmodules就不再需要数据了。6
5请注意,您可以创建一种半途而废的子模块,其中子.gitmodules模块没有文件条目,但在超级项目的提交中存储了 gitlink。
6有些git submodule命令仍会.gitmodules为您更新,有些git submodule命令使用从 复制.gitmodules到 的数据.git/config。但是,一旦克隆了子模块,这些都不需要日常使用。
git clone如果 Git 存储库 A 将 Git 存储库 B 列为子模块(在 A.gitmodules和 gitlinks-in-commits 中),并且 Git 存储库 B 将 Git 存储库 A 列为子模块(在 B.gitmodules和 gitlinks-in-commits 中),任何克隆并签出提交并指示子模块克隆并签出其提交的自动化操作都可能导致无限递归:
那么,这里真正的关键是那些git clone和/或git checkout步骤。超级项目什么时候运行git clone?超级项目何时将子模块定向到git checkout某些提交?
如果您关闭子模块递归模式,答案是超级项目永远不会自行运行git clone,也永远不会自行运行git checkout。这使您能够:
然后停下来。
\n如果你打开递归, A将克隆B并告诉它检查提交,这可能会告诉B克隆A,并且由于递归打开,这将永远持续下去(或者直到你用完磁盘空间为止)。因此,只需关闭递归即可,\xe2\x80\x94 就可以了,但是使用这些存储库的每个人都必须知道这样做。
\n如果可能,您应该添加一个额外的存储库,它将记录这些依赖项:
RepoTnParent
RepoTn
RepoTh
RepoCommon
Run Code Online (Sandbox Code Playgroud)
这样,如果您需要构建RepoTn,您将加载 ,RepoTnParent这将依次加载正确的版本RepoTn,RepoTh和RepoCommon。
| 归档时间: |
|
| 查看次数: |
944 次 |
| 最近记录: |