Git SubModule

添加子模块

进入某个项目,执行:

git submodule add https://git.coding.net/Grampus/hmb_yaf_framework.git system

完成后通过 git status 会发现多了两个东东:

new file:   .gitmodules
new file:   system

其中 .gitmodules 文件的内容如下:

[submodule "hmb_yaf_framework"]
    path = system
    url = https://git.coding.net/Grampus/hmb_yaf_framework.git

保存并推送:

git add system
git commit -a -m '增加子模块'
git push -u origin master

拉取子模块到最新

cd system && git pull origin master

回到上级目录敲 git status,会显示:

modified:   system (new commits)

为什么子模块 system 目录会有一个新变更?

其实,Git 在顶级项目中记录了一个子模块的提交日志的指针,用于保存子模块的提交日志所处的位置,以保证无论子模块是否有新的提交,在任何一个地方克隆下顶级项目时,各个子模块的记录是一致的。作用类似于 composer.lock 或者 yarn.lock,避免因为所引用的子模块不一致导致的潜在问题。

如果我们更新了子模块,我们需要把这个最近的记录提交到版本库中,以方便和其他人协同。

提交这个子模块版本锁:

git add system
git commit -a -m "更新子模块"
git push origin master

批量拉取所有子模块到最新(强烈推荐)

git submodule foreach git pull origin master

协作者如何更新子模块?(非常重要的场景)

场景:本地更新了子模块代码,同时提交了子模块 commit_id,那么其他开发者如何获得这些更新?

git submodule update

这条命令的作用是,拉取所有数据并 checkout 到指定 commit_id

切记不能用 cd system && git pull origin master,这只会拉取到子模块到最新,无视了子模块版本锁。

如何克隆含子模块的仓库?

方式1:

git clone https://git.coding.net/grampus/hmb_2c_server.git
cd hmb_2c_server
git submodule update --init --recursive
cd system && git checkout master && cd ..

方式2:

git clone --recursive https://git.coding.net/grampus/hmb_2c_server.git
cd hmb_2c_server/system && git checkout master && cd ..

参数 --recursive--recurse-submodules 的意思是:

可以在 clone 项目时同时 clone 关联的 submodules。

After the clone is created, initialize all submodules within, using their default settings. This is equivalent to running git submodule update --init --recursive immediately after the clone is finished. This option is ignored if the cloned repository does not have a worktree/checkout (i.e. if any of –no-checkout/-n, –bare, or –mirror is given)

注意:子模块默认不在任何分支上:Not currently on any branch ,需要手动 cd system && git checkout master && cd ..

删除子模块

git rm -r <SubModuleName>

例如:

git rm -r system
git commit -m "删除子模块"
git push origin master

参考文章