子模块的使用
添加子模块
-
添加子模块
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