子模块的使用
添加子模块
-
添加子模块
git submodule add <子仓库URL> <子仓库路径>例子: git submodule add http://192.168.100.181/guideir/poco.git 3rdparty/poco
-
若子模块存在好几个分支,可以在添加子模块时,指定分支
git submodule add -b <分支名> <子仓库URL> <子仓库路径>例子:git submodule add -b build_V1.9.4_ar9341 http://192.168.100.181/guideir/poco.git 3rdparty/poco
执行此命令后可以在
.gitmodules文件中看到如下配置:[submodule "poco"] path = 3rdparty/poco url = http://192.168.100.181/guideir/poco.git branch = build_V1.9.4_ar9341
下载子模块
使用 git clone 下载代码时,如果使用普通的 git clone来克隆项目,会发现项目的子模块文件夹中内容为空
可以使用以下两种方式来克隆子项目:
-
克隆主项目时候,使用
git clone --recurse-submodules <主仓库URL>递归克隆子模块例子:git clone --recurse-submodule https://gitee.com/oweni/config-test.git
git clone --recurse-submodule
是 Git 2.13 版本引入的,为了提高命令的可读性。在之前的版本中,可以使用git clone --recursive`指令,无论是哪种写法,都会递归地克隆主仓库及其所有子模块 -
若已经克隆完成主项目,但是此时子模块文件夹为空,可以在主仓库目录中使用
git submodule update --init指令下载子模块例子:
- 下载主仓库代码: git clone https://gitee.com/oweni/config-test.git
- 在主仓库目录使用:
git submodule update --init或者git submodule update --init --recursive递归下载子模块
-
若已经下载完成子模块,发现子模块不是最新代码,可以在主仓库目录使用: git submodule update --remote 或者 git submodule update --remote --recursive 指令将子模块更新到子模块的最新节点;
注意:
git submodule update是将子仓更新到主仓库当前引用的节点,注意,主仓库当前引用的节点,并不一定是子仓库的最新节点;而git submodule update --remote是将子仓库更新到子仓库的最新节点,所以通常在执行完git submodule update --remote指令后,也许主仓库会提示子仓库有新提交,此时在父仓库中add + commit + push当前改动,将主仓库引用的子仓库节点更新到最新
修改子模块代
1.正常情况,进入子仓库,使用git status 查看当前是否处于某个分支,如果是处于正常的分支,那么可以直接进行添加和提交,和普通的提交流程一样
$ git add .
$ git commit -m "commit"
$ git push origin master
2.异常情况,如果进入子仓库,发现子仓库的状态为 头指针分离于 XXXX(commit id),此时有两种解决方案提交:
方案一
1.使用 git add 和 git commit来添加和提交修改到本地
git add <change files>
git commit -m "fix some bugs"
2.推送修改到子仓库的远端,在头指针分离的情况下,如下提交:
git push origin HEAD:master
//推送当前修改到远端的master分支上
3.回到父仓库中,提交对子模块的更新
cd .. //回到上级目录(父仓库)
git add son //son为子仓库的目录
git commit -m "update son submodule"
git push origin master
方案二
解决方法是:在子模块中先git checkout master,然后在git merge <detached branch name/number>,最后git push -u origin master即可。如图:

解释下出现 头指针分离的原因:
这里有个概念,就是主repo中的子模块被拉到本地时默认是一个子模块远程仓库master分支的detached branch。这个分支是master的拷贝,但它不会被推送到远端。如果在子模块中做了修改,并且已经add,commit,那你会发现当你想要push的时候会报错:Updates were rejected because a pushed branch tip is behind its remote。这便是所谓的detached branch的最直接的体现。
删除子模块
使用git submodule deint指令来删除子模块
提供一个例子,删除trunk/3rdparty/ffmpeg子模块,之后再引入trunk/3rdparty/ffmpeg子模块:
1.git submodule deinit -f trunk/3rdparty/ffmpeg,删除 trunk/3rdparty/ffmpeg子模块
此时本地代码目录trunk/3rdparty/ffmpeg中的代码会被删除,但是此文件夹会存留
2.手动删除.git/modules/目录中相关子模块的文件夹
rm -rf .git/modules/trunk/3rdparty/ffmpeg/
3.执行git rm trunk/3rdparty/ffmpeg, 删除此子模块在git中的记录,
此操作会删除以下两个内容:
.gitmodule文件中关于这个子模块的配置
[submodule "trunk/3rdparty/ffmpeg"]
path = trunk/3rdparty/ffmpeg
url = ssh://git@192.168.100.181:2222/guideir/ffmpeg.git
branch = build_V4.2.1_ar9341
- 本地代码目录
trunk/3rdparty/ffmpeg目录
执行完以上三个步骤,则子模块被完全清除干净,接下来再添加子模块
4.添加子模块
git submodule add -b build_V4.2.1_ar9341 ssh://git@192.168.100.181:2222/guideir/ffmpeg.git trunk/3rdparty/ffmpeg
注意事项:
- 如果没有执行删除操作中的第2步,则添加子模块时会报错:

- 如果没有执行删除操作中的第3步,则添加子模块时会报错

git pro


















