查看 git 提交,包括当时的子模块

Check out a git commit including submodules as they were at that time

我们如何检查包含子模块的 git 提交,它们当时

我们可能想要这样做的一个原因是查看主程序的先前版本,我们需要使用提交时使用的版本中的子模块重建主程序。

鉴于此,我们甚至可以在常规工作流程中使用它:

我们可以通过手动查看每个子模块来做到这一点:哪个提交具有适当的时间戳(并希望该程序使用当时最新的版本)。如果我们能看到程序的提交 X 使用了子模块提交 Y,那就更好了。并检查每个子模块。

在这种情况下,您只需要 运行 git submodule update --checkout(没有 --merge,没有 --remote)检查之前的提交。

关于子模块有很多混淆。虽然基础实际上相当简单:

  • 每个子模块都是自己的 Git 存储库。
  • 从子模块中,将 "containing" Git 称为 超级项目
  • 超级项目记录 URL 和路径——这些是您通常由 运行ning git clone 控制或提供的东西——对于 .gitmodules 中的每个子模块] 文件。
  • 同时,当您在超级项目中进行提交时,此提交在其快照中像往常一样包含所有正常的树和文件,而且对于每个子模块,在检出子模块。1

这具有 "freezing" 将适当的子模块提交到每个超级项目提交中的效果。它是——或者最初是——用于管理第三方代码,与超级项目相比,子模块本身很少改变。

这种模式一点都不灵活,不适合很多人想要使用子模块的方式,也就是把子模块放在某个分支的顶端。因此,子模块增加了更新分支名称的能力,或者成为 worked-in 并使工作变基 and/or 合并。这些新能力产生了 子模块。<em>name</em>.update 配置条目和 git submodule update --remote 选项。

如果您没有配置任何这些项目git submodule update将单独检查当前记录的每个子模块所需的(记录的)子模块提交,即, HEAD, 超级项目的提交。如果您已经配置了其中的一些,您可以使用git submodule update --checkout覆盖配置并导致git检出<em>hash-id</em> 在每个子模块中。请注意,添加 --force 会使 Git 执行此子模块检出,即使 HEAD 已经在该条目中。但是由于每个子模块都是它自己的 Git 存储库,因此子模块的签出与它自己的 (per-repository / per-work-tree) 索引和 work-tree. 有自己的交互2

同样,每个子模块都是自己的 Git 存储库,这意味着当前超级项目的子模块可能有自己的子模块。如果是这样,这也使子模块成为超级项目,这就是 --recursive 标志的用武之地。如果您不嵌套子模块,none 这种复杂性将影响您。


1换句话说,超级项目的index每个子模块都有一个条目。这个索引条目的类型是"gitlink",它存储了子模块中从HEAD读取的SHA-1。这些 gitlink 条目被视为 symlink 和目录之间的一种奇怪的交叉。

2也就是说,如果你手动输入了其中一个子模块并修改了索引and/or work-tree,那么git checkout 运行 inside 该子模块(如果有)可能仍会将您的修改带入新的 checked-out 提交。