Git Submodule
在做不同的项目,但是又都会使用到一些常用的方法组件代码块等等。
作为一个追求优雅的开发人员,肯定不能接受一段代码到处复制粘贴的操作。而且一旦这段代码日后需要更新,到处粘贴的话就需要全局搜索然后含泪修改了。
那么有没有一种办法,能够作为一些公共代码的“栖息地”,可以做到一处编写,到处使用呢?
答案是有的,使用git内置功能submodule即可。
有种情况我们经常会遇到:某个工作中的项目需要包含并使用另一个项目。 也许是第三方库,或者你独立开发的,用于多个父项目的库。 现在问题来了:你想要把它们当做两个独立的项目,同时又想在一个项目中使用另一个。
Git 通过子模块来解决这个问题。 子模块允许你将一个 Git 仓库作为另一个 Git 仓库的子目录。 它能让你将另一个仓库克隆到自己的项目中,同时还保持提交的独立。
新建SubModule
要为父仓库添加子仓库,首先你需要创建父仓库和子仓库。
将父仓库克隆至本地:
git clone https://gitee.com/xiaomumaozi/SubModule_Test.git
然后使用命令添加:
//git submodule add <仓库地址> <本地路径>
git submodule add https://gitee.com/xiaomumaozi/SubModule.git src/SubModule
添加成功后,在项目src目录中能够看到新增的文件夹SubModule。
另外新增了文件.gitmodules,在里面增加了对SubModule的一些描述。
除此之外,执行命令
cat .git/config
可以发现在父仓库的git 配置文件(.git/config)中加入了submodule段。
到这里新增SubModule就完成了。
- clone有SubModule的项目
如果要clone一个附带submodule的项目,submodule的文件
不会自动随父项目clone出来(其实只会clone出 .gitsubmodle 这个描述文件),
还需要执行如下命令取出submodule里的文件:
# 用来初始化本地配置文件
git submodule init
# 从该项目中抓取所有数据并检出父项目中列出的合适的提交(指定的提交)。
git submodule update
(以上两条命令也可以合并成一条组合命令:git submodule update --init --recursive)
------------------更好的方式---------------------
# clone 父仓库的时候加上 --recursive,会自动初始化并更新仓库中的每一个子模块
git clone --recursive https://gitee.com/xiaomumaozi/SubModule_Test.git
更新SubModule
在父仓库目录下git pull之后,立即执行
git status
如果发现submodule有修改,
立即执行
git submodule update --remote
在主仓库下执行git submodule update --remote等价于进入 submodule 目录内,然后执行 git pull, 这两个操作都会把 submodule 目录中的文件更新到最新。
更复杂一些,如果你的submodule又依赖了submodule,那么很可能你需要在git pull 和 git submodule update之后,再分别到每个submodule中再执行一次git submodule update,
这里可以使用 git submodule foreach命令来实现:
git submodule foreach git submodule update
修改Submodule
有些时候你需要对submodule做一些修改,很常见的做法就是切到submodule的目录,然后做修改,然后commit和push。
这里的坑在于,默认git submodule update并不会将submodule切到任何branch,
所以,默认下submodule的HEAD是处于游离状态的(‘detached HEAD’ state)。
所以在修改前,记得一定要用
git checkout master
将当前的submodule分支切换到master,
然后才能做修改和提交。
如果你不慎忘记切换到master分支,又做了提交,可以用cherry-pick命令挽救。具体做法如下:
- 1.用 git checkout master 将HEAD从游离状态切换到 master 分支, 这时候,git会报Warning说有一个提交没有在branch上,记住这个提交的change-id(假如change-id为 aaaa)
- 2.用 git cherry-pick aaaa 来将刚刚的提交作用在master分支上
- 3.用 git push 将更新提交到远程版本库中
删除子仓库
- 1.删除.gitsubmodule里相关部分
- 2.删除.git/config 文件里相关字段
- 3.删除子仓库目录。
然后执行命令:
git rm --cached <本地路径>
即可完成删除。