子模块的提交指针模型是什么
父仓库里的子模块记录的不是分支而是「指向某次提交的指针」(索引里的 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 才一致;提交父仓库前想清楚是否要更新指针。