git 子模块的一些快速上手技巧
本地项目:project-main
https://github.com/xxx/project-main.git (仓库地址不可用)
子项目:project-sub
https://github.com/xxx/project-sub.git (仓库地址不可用)
前提:本地已经有一个主项目,但是没有子模块。
命令:git submodule add
注意请用 https
开头的连接,而不是 git
开头的
$ git submodule add https://github.com/xxx/project-sub.git project-sub
添加子模块,然后运行git status
,
可以看到目录有增加2个文件
.gitmodules
,这个文件用来保存子模块的信息。project-sub
,这个就是你所创建的子模块的文件夹$ git status
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached ..." to unstage)
new file: .gitmodules
new file: project-sub
# 根目录下的文件:.gitmodules
[submodule "project-sub"]
path = project-sub
url = https://github.com/xxx/project-sub.git
如果此前项目中已经存在 .gitmodules
文件,则会在文件内容中多出上述三行记录。
这时候,建议先提交一次
commit
$ git submodule
e33f854d3f51f5ebd771a68da05ad0371a3c0570 project-sub (heads/master)
还有一种情况是,带有子模块的主项目需要从仓库中拉取
$ git clone https://github.com/xxx/project-main.git
在主项目文件夹中,有 project-sub
该文件夹
但是里面是空的
# 子模块前面有一个`-`,说明子模块文件还未检入(空文件夹)。
$ git submodule
-e33f854d3f51f5ebd771a68da05ad0371a3c0570 assets
$ ls project-sub
$
这个时候,需要执行两个:init + update
# 进入到 project-sub 同级目录
$ git submodule init
$ git submodule update
另外一种不用手动更新子模块的方式(不适合分支子模块)
$ git clone https://github.com/xxx/project-main.git --recurse-submodules
使用查看命令来观察项目变动是一个好习惯
$ git status
# 查看版本异同
$ git diff
$ git diff --submodule
开发环境居多,直接在项目中更改代码,但是没有递交到远程仓库
有一种情况,你忘了子模块推送,直接把主项目推送了,造成了版本紊乱,悔之晚矣。这时候需要 git
来校验我们是否将子模块推送了
$ git push --recurse-submodules=check
负责子模块开发的人做了一些版本升级工作
方式一:进入到子文件夹,同步远程仓库
# 进入到子文件夹,像同步远程仓库一样操作
$ cd project-sub
# 拉取仓库方式1
$ git fetch
$ git merge origin/master
# 拉取仓库方式2 (建议)
$ git pull --rebase
方式二:在主项目中进行更新,默认是 master
分支,更改分支改动在 .gitmodules
或者 .git/config
文件中
$ git submodule update --remote
# 更改分支
$ git config -f .gitmodules submodule.project-sub.branch <branch_name>
在这个时候呢,还有一种情况,远程仓库有了版本升级,要同步远程仓库
# 在主项目中执行拉取操作,不会同步更新子模块
$ git pull
# 同步远程主项目和子模块
$ git pull --recurse-submodules
有一种情况,子模块变更了托管的平台。此时,若父级项目引用的子模块提交不在仓库中本地配置的子模块远端上,那么执行 git pull --recurse-submodules
或 git submodule update
就会失败。
在你写 ci
的时候,需要极其注意这个东西。因为好的 ci
,只需要写一遍就够了。
# 将新的 URL 复制到本地配置中
$ git submodule sync --recursive
# 从新 URL 更新子模块
$ git submodule update --init --recursive
当你有多个子模块的时候,想要对所有子模块执行相同的操作,比如更新子模块远程仓库,需要一个一个修改过去特别麻瓜。
这个时候就需要使用下面这个命令
git submodule foreach 'git pull origin master'
# 在子模块同级目录下面
$ git submodule deinit project-sub
# 连同子模块工作区的工作一块删除
$ git submodule deinit project-sub --force
上面的命令执行的工作流程等同于下面方式二
删除子模块文件夹
$ git rm --cached project-sub
$ rm -rf project-sub
删除 .gitmodules
文件中相关子模块信息
[submodule "project-sub"]
path = assets
url = https://github.com/xxx/project-sub.git
删除 .git/config
中的相关子模块信息
[submodule "project-sub"]
url = https://github.com/xxx/project-sub.git
删除 .git
文件夹中的相关子模块文件
$ rm -rf .git/modules/project-sub