老高最近的项目用到了git的submodule,期间遇到了很多坑,比如:
如何更新submodule 如何修改并提交submodule 如何将submodule的变更在父项目中提交
在弄明白这些问题之前,首先我们需要理解git的submodule到底是个啥。
其实父项目与子模块(submodule)之间的关系很松散,父项目基本只关心子模块的地址以及版本(commit id)。
我们在子模块如何改动父项目是不需要关心的,只需要把改动的版本号告诉给父项目就行。
下面我们试着解决几个问题:
git submodule add https://github.com/phpgao/BaiduSubmit.git usr/plugins/BaiduSubmit
git submodule add https://github.com/phpgao/TableOfContents.git usr/plugins/TableOfContents
git submodule add https://github.com/phpgao/ExternalTool.git usr/plugins/ExternalTool
git submodule add https://github.com/phpgao/CdnHelper usr/plugins/CdnHelper
这个时候如果你留意一下.gitmodules
和.git/config
这两个文件,应该会发现相关信息已被记录下来!
当clone项目时有子模块存在时,第一次是不会顺便clone出子模块的,需要执行一些命令:
git clone xxx.git
# 初始化子模块
git submodule init
# 将子模块的文件check出来
git submodule update
# 现在所有子模块已经把被checkout到本地,是不是很棒!
但是,如何删除submodule呢?大家第一时间一定想到的是remove,但是git貌似没有提供类似 git submodule remove
那么easy的方法,所以我们要借助deinit。所以如果之前你是直接编辑.gitmodules文件就以为删除了那你就错了!
# 我们以BaiduSubmit为例,之前我们添加在了 usr/plugins/BaiduSubmit
# 首先我们反初始化
git submodule deinit usr/plugins/BaiduSubmit
# 此时 .git/config 已被重写,BaiduSubmit的相关信息已经不存在了
git rm usr/plugins/BaiduSubmit
# 这时,子模块文件被删除,同时 .gitmodules 文件中的相关信息被删除
# 还有一种情况,就是子模块刚被add,但是还没有commit的时候,这时如果反悔了,但是还想保留工作现场,可以这样。
# 如果不想保留,看下一条
git rm --cached usr/plugins/BaiduSubmit
rm -rf .git/modules/usr/plugins/BaiduSubmit
# 或者直接全部删除
git submodule deinit --force usr/plugins/BaiduSubmit
这里分两种情况,一个是本人直接在子项目修改并提交,另一种是别人的git仓库被修改
其实我们只需要注意一点,就是子模块的分支出于游离状态,我们在修改他的时候第一步需要执行检出对应的分支即可!
# 首先,我们进入子模块
cd xx/xx/sub
# 检出master分支
git checkout master
# 然后做修改
vim some-file.py
# 最后做提交
git add .
git commit -m "Get something done"
git push origin master
当子模块是别人维护的时候,当他更新的时候,我们需要怎么做?
# 首先检出master分支
git checkout master
# 然后拉取更新
git pull
# 回到父项目中更新
cd ../../
git add xx/xx/xx
git commit -m "update submodule"
子模块被提交后父项目会检测到,正常提交即可!
git status
# modified: xx/xxxx/xxxx (new commits)
# add的时候注意再最后不要加 / 斜杠,否则会出现很棘手问题
git add xx/xxxx/xxxx
git commit -m "update submodule"
git push