git submodule特点
Git submodule 从来不“跟随分支”,它只记录一个“精确的 commit”,像把子仓库钉死在某个时间切片上。
注意点:
- 父仓库并不存子仓库的分支名。
- 仓库只在
.gitmodules里记录路径和 URL。 - 真正决定子模块内容的是父仓库里记录的那个 commit SHA。
意味着你主仓库有:
- master
- dev
- feature-x
每个分支都可以指向子仓库的不同 commit(哪怕都来自子仓库 master 分支)这完全没问题。
每个分支都对应子仓库的master 分支
1.固定版本模式
子仓库正常开发在 master。
父仓库某个分支只在需要升级时:
cd submodule
git checkout master
git pull
cd ..
git add submodule
git commit -m "bump submodule"
父仓库就记录了子仓库最新的那个 commit。
优点:
可控、可回滚、可审计。
缺点:
不是自动跟随。
2.自动跟随模式
在 .gitmodules 里加:
branch = master
然后:
git submodule update --remote
它会拉子仓库 master 最新 commit,并更新父仓库索引,但注意,父仓库仍然是记录具体 commit,不是记录“master”所以所谓“对应 master 分支”,只是通过 update –remote 达成的一种同步行为,而不是动态绑定。
submodule合并
假设:
- 父仓库 master 分支记录子仓库 commit A
- 父仓库 dev 分支记录子仓库 commit B
当你合并 dev -> master 时:
Git 看到的是:
子模块路径这个文件的 SHA 变了
它并不理解子仓库历史。
它只会判断:
- 如果两个分支子模块指向不同 commit
- 并且没有祖先关系
那就会产生冲突:
CONFLICT (submodule)
这时候需要你手动决定:
cd submodule
git checkout 想要的commit
cd ..
git add submodule
git commit
所以:
合并不会“出问题”,
但它不会自动替你做子仓库的 merge。
submodule 是“强一致引用机制”,不是“多仓库分支联动系统”。
它更像是:
父仓库记录一个外部依赖的精确版本
如果你希望多分支与子仓库分支强绑定、自动联动、自动 merge,那 submodule 不是理想工具。
架构层面理解submodule
graph TD
A[Parent Repo - master] -->|records| C1[submodule commit A]
B[Parent Repo - dev] -->|records| C2[submodule commit B]
C1 --> S[Submodule Repo]
C2 --> S
note1[Parent stores commit SHA only]
重点是:
父仓库存的是 commit ID,不是 branch。
注意:很多大型项目后来都放弃了 submodule,因为跨分支协作时它非常容易制造“引用错位”。