Git 子模块必须在子目录中吗?

Do Git Sub-modules have to be in a Sub-directory?

我正在使用包含子模块的子模块的存储库中的项目。我注意到一些子模块依赖于已经包含在不同子模块中的子模块,我想清理一些存储库。

对我来说最明显的解决方案是将实际的子模块存储库移动到我的 git 目录的根目录(因此它们的目录与项目 A 的目录位于同一位置),并使用每个目录中的符号链接(或其他东西),这样代码就不会在主存储库中重复。

这可能吗?

要"draw"出来,我有(箭头指向子模块依赖项的地方)

~/A
  |->~/A/B
  |->~/A/C
         |->~/A/C/B

我想对其进行修改,以便我拥有:

~/A--|
     |___
~/B<-|<-|-|
~/C<----| |
  |_______|

这样,每次存储库依赖它时,我都不会复制来自 B 的代码(我的许多项目都依赖它)。

是的,他们有。也就是说,对于 Git 存储库 Rbe 具有子模块 S 的超级项目,子模块必须在超级项目的工作树中显示为某个路径 path/to/submodulepath/to/部分可以为空,submodule部分不可以。

这样做的原因是:

  • 超级项目R有一些子模块S的事实是记录在 R.gitmodules 文件中,然后记录在 R.git/config 文件中。特别是,Rgit submodule init 应该使用的 URL 在某些 .gitmodules 文件中(出现在多个提交中)。该子模块的路径是一些非空路径 P,并且 P 和 URL 都被复制到 .git/config

    一旦这些在 .git/config 文件中,您就可以在 .git/config 文件中更改它们。 Git 将使用这些而不是 .gitmodules 文件中的值。继续将正确的路径和 URL 提交到 .gitmodules 是个好主意,因为 future git clone <em>R</em> 很可能会使用分支提示的 .gitmodules 文件来填充未来克隆的 .git/config 文件。 (这取决于谁 运行s git clone 以确保他们正确填充文件。使用选定的提示提交的 .gitmodules 文件是填充它的默认方式。)

  • 但是,更重要的是,在任何时候,子模块都应该使用 一个特定的提交。即超级工程会运行cd path/to/submodule(cd<em>P</em>)然后发出命令:git结帐<em>散列</em>。这将 S 放在给定散列的分离 HEAD 上。此操作在您 运行 git submodule update.1 时完成 一个特定的提交被记录为 gitlinkR 中的每个提交中。 gitlink 作为路径为 P 的条目存在于索引中(从中进行新提交)。索引只能保存存在于或至少存在于存储库 R.

    工作树中的文件路径

所以为了R控制S,Git会坚持S 位于 R.

的子目录中

如果你不需要 R 来控制 S——如果你只想 git clone 自己控制几个仓库,并且在 R 中没有提交存储 gitlink 条目,这些条目持有已采用的哈希 ID(没有 S 的知识或consent) from S—那么你可以完全放弃使用子模块的想法,并获得你想要的布局。


1您可以通过各种标志和其他操作和选项更改传递给此 git checkout 的参数,但正常情况是这种分离的 HEAD,即使您在 .gitmodules 文件中为 S 指定了分支名称 and/or 您的 .git/config.