git clone 时如何连子模块(submodule)一起克隆
克隆带子模块的仓库:git clone --recursive <仓库地址>(等价 --recurse-submodules)。已经克隆了再补:git submodule update --init --recursive。更新子模块到最新用 git submodule update --remote。
加 --recursive 参数:git clone --recursive <仓库地址>,主仓库和它的所有子模块(包括子模块的子模块)会一次性全部拉下来。如果已经普通克隆了,补一句 git submodule update --init --recursive 效果相同。
两种场景
# 场景一:首次克隆
git clone --recursive https://github.com/org/repo.git
# 场景二:已经克隆了,补上子模块
git submodule update --init --recursive
--init:按 .gitmodules 初始化配置;--recursive:处理嵌套子模块。
日常协作命令
git pull --recurse-submodules # 拉主仓库并同步子模块
git submodule update --remote # 子模块更新到其远程分支最新提交
git submodule status # 查看各子模块当前指向的提交
在 .gitconfig 里设 submodule.recurse=true 可以让 pull/checkout 自动处理子模块。
子模块的本质
主仓库只记录子模块的仓库地址 + 固定提交哈希(gitlink)。克隆主仓库时子模块目录是空的,必须 init+update 才会真正拉代码。主仓库更新子模块指向时,协作者要跑 git submodule update 才能跟上。
常见问题(FAQ)
Q:CI 里克隆带子模块的仓库要注意什么?
各平台 checkout 步骤一般有 submodules: recursive 选项,勾选即可;私有子模块要确保 CI 的凭据对子模块仓库同样有权限。
Q:子模块目录里 git 操作和普通仓库一样吗?
一样——它就是一个独立仓库(有自己的 .git 文件指向主仓 modules 目录)。在里面提交的改动要先在子模块内 push,再回主仓库提交子模块的新指向,两步缺一不可。
Q:不想要子模块了怎么移除?
三步:git submodule deinit -f <路径>、git rm <路径>、删除 .git/modules/<路径> 残留目录,然后提交。