子模块允许你将一个 Git 仓库作为另一个 Git 仓库的子目录。 它能让你将另一个仓库克隆到自己的项目中,同时还保持提交的独立

场景: 当项目依赖并跟踪一个开源的第三方库时,将第三方库设置为submodule

初始化模块 - git submodule add

cd third && git submodule add <https://github.com/hibernate/hibernate-orm>

子模块现在已经关联到主仓库,并且clone了子模块;

如果后续我们clone主项目,子模块的代码默认会是空的,我们可以

git clone  --recurse-submodules git@github.com:HelloAnner/DFJ.git 

这样会递归地将项目中所有子模块的代码拉取

另外一种可行的方式是,在当前主项目中执行:

git submodule init
git submodule update

会根据主项目的配置信息,拉取更新子模块中的代码

更新子模块

对于子模块而言,并不需要知道引用自己的主项目的存在。对于自身来讲,子模块就是一个完整的 Git 仓库,按照正常的 Git 代码管理规范操作即可

子模块有未跟踪的内容变动

在开发环境中,直接修改子模块文件夹中的代码

git status能够看到关于子模块尚未暂存以备提交的变更,但是于主项目使用 git add/commit对其也不会产生影响

在此情景下,通常需要进入子模块文件夹,按照子模块内部的版本控制体系提交代码 (git add),然后下述情况

子模块有版本变化

当子模块版本变化时,在主项目中使用 git status查看仓库状态时,会显示子模块有新的提交

在这种情况下,可以使用 git add/commit将其添加到主项目的代码提交中,实际的改动就是那个子模块 文件所表示的版本信息

通常当子项目更新后,主项目修改其所依赖的版本时,会产生如下这种情景的 commit 提交信息:

git diff HEAD HEAD^
diff --git a/project-sub-1 b/project-sub-1
index ace9770..7097c48 160000
--- a/project-sub-1
+++ b/project-sub-1
@@ -1 +1 @@
-Subproject commit ace977071f94f4f88935f9bb9a33ac0f8b4ba935
+Subproject commit 7097c4887798b71cee360e99815f7dbd1aa17eb4

子模块远程有更新

需要让主项目主动进入子模块拉取新版代码,进行升级操作

git pull origin master

当主项目的子项目特别多时,可能会不太方便,此时可以使用 git submodule的一个命令 foreach执行:

git submodule foreach 'git pull origin master'

如果在主项目 git pull , 会递归地抓取子模块的更改, 但是不会更新子模块,需要:

git pull  --recurse-submodules
 
# 等价于
 
git submodule update --init --recursive

删除子模块

根据官方文档的说明,应该使用 git submodule deinit命令卸载一个子模块。这个命令如果添加上参数 --force,则子模块工作区内即使有本地的修改,也会被移除