Workflows
子模块更新流程教程
梳理子模块仓库更新、锁定版本和主仓库同步的基本流程。
- 要把命令组合成稳定流程的团队成员
- 需要处理协作顺序和分支边界的人
- 知道 fetch / pull / push / branch 的基本作用
- 能理解一条分支为什么会分叉
- 照抄流程却没确认当前分支关系
- 在共享分支上用错整合方式
子模块工作流最容易让人困惑的一点是:
你看起来像是在更新一个目录,实际上是在同时处理两层仓库:
- 子模块仓库自身的提交历史
- 主仓库里记录的“子模块指针”
如果不把这两层分开看,就会反复遇到“明明改了子模块,主仓库为什么还显示变化”这种典型困惑。
submodule repo目标提交递归初始化状态
子模块到目标提交主仓库记录新指针别人可递归同步
主仓库提交的不是子模块文件内容,而是它指向哪个提交。
这个流程为什么容易出错
子模块不是普通目录。
它更像“主仓库引用的另一个仓库状态”。所以每次更新都必须同时想清楚两件事:
- 子模块仓库自己现在在哪个提交
- 主仓库准备记录哪个子模块提交作为团队基线
少看任何一层,后面都会出问题。
推荐顺序
1. 先在子模块里切到目标提交
git submodule update --init --recursive
cd path/to/submodule
git fetch origin
git switch main
git pull --ff-only
这一步的目标,是先让子模块仓库自身到达你想要的提交,而不是立刻回主仓库提交。
2. 再回到主仓库提交子模块指针变化
cd ../..
git status
git add path/to/submodule
git commit -m "chore: update submodule pointer"
主仓库提交的不是子模块源码本身,而是“这个目录现在应当指向哪个子模块提交”。
3. 最后统一验证初始化和递归更新
git submodule update --init --recursive
这一步的意义,是验证其他开发者拿到主仓库最新状态后,能否递归拿到一致的子模块状态。
一个完整的更新示例
git submodule update --init --recursive
cd path/to/submodule
git fetch origin
git switch main
git pull --ff-only
cd ../..
git status
git diff --submodule
git add path/to/submodule
git commit -m "chore: update submodule pointer"
这一套流程的核心价值,是把“子模块自己怎么更新”和“主仓库怎么记录这次更新”严格拆开。
哪些检查点最值得坚持
每次更新子模块时,至少确认:
- 子模块自己是否已经到目标提交
- 主仓库里是不是只出现了预期的子模块指针变化
git diff --submodule的差异是否可解释- 递归初始化之后,别人的工作区能否得到一致状态
什么时候子模块流程会特别危险
- 子模块自己仍在功能分支上,不是稳定提交
- 团队没有统一初始化和递归更新命令
- 有多层嵌套子模块,但大家忘记带
--recursive - 主仓库和子模块的权限、分支策略不同步
这些问题会让“只是更新一个依赖仓库”迅速变成协作故障。
子模块目录的内容变化只是表象。真正被主仓库记录的是一个提交指针。如果只看文件树、不看子模块提交状态,你很容易误判自己到底更新了什么。
常见误区
以为主仓库提交的是子模块文件内容
通常不是。
主仓库提交的是子模块引用到哪个提交。
只更新了子模块仓库,没有提交主仓库指针
这样别人拉主仓库时,仍然拿不到你想要的子模块版本。
忘记初始化子模块就开始工作
这会让本地状态看起来“不完整”,甚至误以为仓库坏了。
以为更新子模块不需要 review
子模块指针变化本身就应该 review,因为它代表团队基线依赖变了。
- 子模块当前是不是已经在稳定提交上?
- 这次更新会不会带来额外配置或 API 变化?
- 主仓库里最终只应该出现哪一个子模块路径变化?
- 别人执行递归更新后,能不能得到和你一样的状态?
接下来建议继续学什么
Release branch workflowFeature branch collaborationSync before review