首页/开发/Git 与协作速查/子模块的提交指针模型
进阶与大仓实践69 条

子模块的提交指针模型

父仓库中的子模块记录的是「子树对象指向某次提交」,不是分支:切换父仓库分支会带着指针变化,理解这点才能正确更新与回滚子模块。

Git 与协作速查开发更新于 2026-10-13

子模块的提交指针模型是什么

父仓库里的子模块记录的不是分支而是「指向某次提交的指针」(索引里的 gitlink 条目):切换父仓库分支会改变记录的指针目标,但子模块工作区不会自动跟着变,需要 submodule update。理解这个模型才能正确处理更新与回滚。

基本信息

本质gitlink 记录子模块提交 SHA(索引中的特殊条目)
切换父分支子模块目录不会自动跟着变,需要 submodule update
查看git diff --submodule 与 git submodule status
回滚回滚父提交后子模块仍停在旧检出,需要再次 update
边界子模块目录里切分支不影响父仓库记录,只影响本地检出

典型使用场景

  • 更新子模块:父分支切换后按记录同步子模块指针。
  • 提交指针变更:子模块升级后父仓库需要提交新的 gitlink。
  • 回滚操作:回退父仓库提交后补一次 update 使子模块一致。
  • 代码评审:diff --submodule 把指针变化展示成提交区间。
  • 构建排查:构建用了错误子模块版本时先检查指针是否一致。
  • 文档说明:向团队解释「为什么切分支后子模块没变」。
  • CI 对账:检出后比对子模块指针与构建清单,一致再跑流水线。

查看与更新

查看与更新
git ls-tree HEAD vendor/common            # 查看 gitlink 指向的提交
git diff --submodule HEAD~1               # 指针变化按提交区间展示
git submodule update --init --recursive   # 按父仓库记录同步子模块检出
# 子模块目录内切分支只影响本地检出,不改变父仓库记录

操作与指针状态

操作父仓库记录子模块检出
切换父分支随分支变化不变,需要 update
子模块内切分支不变本地变化,易误解
回滚父提交回到旧指针不变,需要 update
提交子模块新版本记录新指针需 add 子模块路径
回滚父仓库提交后,子模块并不会自动回到旧指针,需要再执行一次 submodule update 才一致;提交父仓库前想清楚是否要更新指针。

易错点

  • 父仓库回滚或切换分支后忘记 update,构建出的仍是新版本子模块代码:先核对 status 再构建。
  • 子模块目录里直接切分支不影响父仓库记录,提交父仓库时只会记当前检出提交,容易误提交。
  • 评审时忽略 gitlink 的变化:diff --submodule 才会显示提交区间,普通 diff 只显示哈希行。,评审意见要写清指针变化方向。
  • 把子模块当普通目录复制粘贴会产生半吊子状态,需要重新 init 恢复。;重建链接后用 status 复核指针是否对齐。

数据来源与参考

  • Git 官方文档:git-submodule
  • Pro Git 2nd Edition · 7.11 子模块
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌