正文
1、使用场景
有的时候,我们或许需要在一个项目中包含和使用另外的项目,同时又希望它们能够保持独立的开发
这时,git submodule
就可以很方便地帮我们处理这种情况
它能够将一个仓库作为另外一个仓库的子模块管理,同时保持他们都是独立的提交
2、基本用法
以下是基于父项目的维度管理子模块,在子模块的维度来看,它就和普通的仓库一样
- 添加子模块:
git submodule add
> # 添加子模块到父项目的根目录 > git submodule add <子模块的地址> > # 添加子模块到父项目指定路径 > git submodule add <子模块的地址> <本地路径>
这时我们能看到,在父项目的根目录下多了一个 .gitmodules
文件,并在指定路径中多了一个子模块目录
.gitmodules
文件记录着子模块仓库与其在父项目中路径的映射关系,它要和子模块一起纳入父项目管理
- 查看子模块:
git status
&&git submodule status
> # 查看状态 > git status # 第 1 种情况:子模块中有未追踪的内容,此时父项目不能将其放入暂存区 # Changes not staged for commit: # modified: submodule (untracked content) # # 第 2 种情况:子模块中有修改过的内容,此时父项目不能将其放入暂存区 # Changes not staged for commit: # modified: submodule (modified content) # # 第 3 种情况:子模块中有新的提交,此时父项目可以将其放入暂存区 # Changes not staged for commit: # modified: submodule-children (new commits) # # 第 4 种情况:父项目已经将子模块中新的提交放入暂存区 # Changes to be committed: # modified: submodule-children
> # 查看子模块提交的状态 > git submodule status
- 修改子模块
从子模块的维度来看,其实它就是一个普通的仓库,所有可以应用于普通仓库的操作都可以应用在子模块上
从父项目的维度来看,父项目不会追踪子模块的具体内容,它只会追踪子模块的提交记录
所以,如果子模块的提交记录发生变化,父项目就可以通过 git add 以及 git commit 将其纳入管理
- 更新子模块:
git submodule update
> # 将所有子模块更新为 本地父项目中的子模块仓库最新的版本 > git submodule update > # 将指定子模块更新为 本地父项目中的子模块仓库最新的版本 > git submodule update <submodule path> > # 将指定子模块更新为 远程子模块仓库特定分支中最新的版本 > git submodule update --remote
这里需要注意,当执行完 git submodule update
之后,子模块的 HEAD 会处于一个游离的状态
我们需要手动将 update 的内容合并到合适的分支,或者使用 --merge
参数自动合并到当前分支
> git submodule update --merge
- 克隆带有子模块的项目
> # 方法一:递归克隆 > git clone <父项目的地址> --recursive > # 方法二:先克隆父项目(此时子模块目录为空),然后初始化并更新子模块 > git clone <父项目的地址> && cd <本地仓库> > git submodule update --init --recursive
注意:
- 在父项目切换分支时,子模块是不会自动切换的,所以我们必须手动将子模块更新
git submodule update