blueyi's notes

Follow Excellence,Success will chase you!

0%

Git submodule使用方法

git的submodule可以用于在项目中添加子项目,这样就可以让主项目可以引用子项目的同时,子项目又可以进行独立的版本控制管理。当子项目有了更新之后,可以便捷的在主项目中对相应子项目进行更新。

查看submodule 状态

1
2
3
git submodule
# or
git submodule status

添加submodule

1
2
3
git submodule add [-b master] [remote_repo] [dest_dir]
eg:
git submodule add https://github.com/test/test.git libs/lib1 # 将test添加到本项目根目录下libs/lib1,lib1中即为test项目的根目录

上面的命令会将仓库地址remote_repo项目添加到当前项目的dest_dir文件夹。执行完成之后会在当前项目根目录中多一个.gitmodules文件,并在.git/config中添加submodule字段。实际上执行的内容是首先将项目克隆到指定目录,然后在刚才说的两个文件中进行子模块的注册。所以该操作相当于修改了当前项目,所以可以使用git status查看到新添加了一个目录和一个.gitmodules文件。
现在直接添加并提交当前项目的修改就完成了子模块的添加

克隆带有submodule的项目

两种方式:

先克隆主项目再更新子模块

1
2
3
4
git clone [remote_repo] [dest_dir]  # 克隆主项目
cd dest_dir
git submodule init # 在主项目中注册子模块
git submodule update # 根据注册过的子模块更新各子模块

直接克隆再有子模块的项目时只会建立子模块的目录,并不会把子模块克隆回来,.git/config中也没有submodule字段,此时使用git submodule查看子模块时,可以看到它们commit id前面会有个-。只有执行了后面子模块的init命令后才会在.git/config中注册子模块。update命令执行完才会将子模块拉回主项目中,此时使用git submodule可以看到commit id前面没有了-
对于克隆之后的项目,也可以将initupdate一起执行:

1
git submodule update --init --recursive

递归克隆子模块

1
git clone --recurse-submodules [remote_repo] [dest_dir]  # 克隆项目remote_repo并递归克隆其子模块

等价于上面的那些命令

注意:此时子模块位于临时分支,不在主分支上

更新submodule

上面说了拉回来的子模块位于临时分支,不在主分支上
如果在主项目中的子模块发生了更新,需要首先进入子模块,将子模块切换到主分支,再拉回来。
如果有多个子模块,可以使用如下命令:

1
git submodule foreach [command]

command会在所有子模块中执行,所以可以如下更新所有子模块:

1
2
git submodule foreach git checkout master
git submodule foreach git pull

然后在主模块中提交更新即可

删除submodule

1
2
3
4
git submodule deinit <submodule path>  # 取消submodule的注册,即从`.gitmodules`中删除
git rm <submodule path> && git commit # 删除相应子模块的目录
git rm --cached <submodule path> # 撤消并删除索引中的路径
rm -rf .git/modules/<submodule path> # 删除相应的子模块文件

git submodule deinit <submodule path> 会取消submodule的注册,即从.gitmodules中删除相应的子模块。

其他submodule命令

1
git submodule [--quiet] sync [--recursive] [--] [<path>]

同步已注册的submodule的URL

参考

Welcome to my other publishing channels