Git 子模块是一个独立的存储库吗?

Is a Git submodule an independent repository?

当我查看我的 Git 存储库时,我可以看到主存储库中有一个 .git 文件夹。然后,当我进入子模块时,我可以看到没有名为 .git 的文件夹,但有一个名为 .git 的文件。为什么会有这种差异?

如果子模块是像主存储库一样的实际存储库,并且可以基本上独立于主存储库工作,则不应该两者都有 .git 文件夹或两者都有 .git文件并没有像这样不同?

子模块的 git 存储目录存储在主存储库的 .git/ 目录中。

您可以在 .git/modules/ 下找到它们:

ls .git/modules

是的,每个子模块都是自己独立的存储库。

早期git submodule有一段时间是这样的:超级项目和每个子模块都有自己的.git文件夹。后来决定所有 git 相关文件都应该存储在一个 .git 目录下,即使对于子模块也是如此。所以 git submodule 增加了一个子命令 git submodule absorbgitdirs 将子模块的 .git 目录移动到超级项目的 .git/modules/ 并留下一个文件 .git 指向超级项目的 .git/modules/.

git clone --recursive 自动执行此操作(移动到超级项目的 .git/modules/)。

是的,每个 Git 子模块都是一个独立的存储库。您所看到的称为 gitlink,它是一种使 .git 内容指向其他地方的方法。最初的想法是为此使用符号链接,但是 Windows 需要提升权限或特殊设置才能使用符号链接,因此 Git 不得不使用 gitlinks。

你想对子模块使用 gitlinks 的原因是因为它可以更容易地取消初始化子模块(也就是说,摆脱它的内容)而不会破坏它的历史。如果你有 gitlink,那么只要子模块的工作树是干净的,去初始化它本质上只是目录上的一个 rm -fr,非常方便。此外,因为人们有时会用子模块来做这件事,这意味着他们并没有意外地毁掉他们的历史。

如果您愿意,仍然可以使用单独的 .git 目录,但通常没有充分的理由这样做,除非出于某种原因您的子模块位于单独的挂载点上。

如果您想找到存储库的实际 Git 目录,请执行以下操作:git rev-parse --git-dirgit rev-parse --absolute-git-dir