项目中常常会使用到第三方的 git 库,将三方库整合到项目中最简单的办法就是复制粘贴,可是若是这个库升级了一个很酷炫的功能,你要怎么整合进来呢?(其实就是 git 版的包管理器)git
这就是本次要介绍的 git-submodule 操做,直接把第三方的版本库合并到本身的库中.github
我这里是本身开了两个库作测试,主库叫 body
,另外一个库叫 leg
测试
首先在本地的body
库中添加leg
fetch
git clone https://git.oschina.net/gaofeifps/body.git cd body git submodule add https://git.oschina.net/gaofeifps/leg.git
这时查看下状态会多两个文件url
➜ body git:(master) ✗ git status On branch master Your branch is ahead of 'origin/master' by 1 commit. (use "git push" to publish your local commits) Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: .gitmodules new file: leg
这就多了一个 leg
的库,和一个.gitmodules
的文件,如今提交一下spa
git commit -am "add leg"
本地提交了版本以后能够提交到远程试一下.net
git push
这时去远程库中看的话库中的内容是这样的3d
这里有个奇怪的 leg @ 6dec2fa
,明明是没有的啊?
点一下原来是一个快捷方式,直接给链接到了 leg
库的地址,版本库中不会存第三方引入库的实体文件,而是经过 .gitmodules
的方式存储三方的联系方式,当下载到本地运行的时候才会再拉取文件版本控制
并且这个时候在其余的地方安装body
这个库的时候直接运行 git clone
是生成不了完整的文件的,缺乏了 leg
库的文件
由于这个时候的 body/leg
目录是空的须要多走一步,这时为何呢?咱们下面会讲到缘由指针
git clone https://git.oschina.net/gaofeifps/body.git git submodule init && git submodule update #下面这一句的效果和上面三条命令的效果是同样的,多加了个参数 `--recursive` git clone https://git.oschina.net/gaofeifps/body.git --recursive
这时才是一个完整的库
以前的一些步骤其实还不完整,由于 body/leg
这个目录中的文件并无和主线在一条线上,这也是为何在远程库的 leg 目录是空的,由于在 master 分支里面它确实是空的,文件是在另外一个分支上,咱们先去看一下
cd path/to/body/leg ➜ leg git:(6dec2fa) git branch * (HEAD detached at 6dec2fa) master
别的文件的分支都是 master
到这个文件的时候就是 6dec2fa
分支了,其实这个值也是 leg
库当前的 commitId
并且若是不把第三方的库归入本身的主线的话会很是的危险,由于你对项目中的三方库发生的任何改动都不会对主线产生任何影响,被主线遗忘了,所以咱们还须要接下来的操做
cd path/to/body/leg git checkout master
这里有个问题就是若是body/leg
发生了更新就首先在这个文件中提交一个commit
,而后在body
这个目录下再 commit
一次
第一次 commit 是为了更新 leg
的版本控制,第二次更新是更新body
的版本控制,同时更新 leg
库在body
的指针
若是更新的比较多,能够运行
假设你的项目当中引入了100个第三方的库,你须要同步的时候难道还要每个都要执行:
cd module-dir/ git checkout master git pull
是否是想起了小学被老师罚抄一百遍的恐惧当中了?
少年,多看看文档准没错的,这些东西 git 早就帮你想好了
具体操做能够看一下git help submodule
有相关的介绍的
不想看文档的就直接告诉你
git submodule foreach <command> 好比: git submodule foreach git checkout master
这条命令就会按照 .gitmodules
会根据path
寻找全部的三方模块,并在每个模块中都执行 foreach
后的命令,
好比你想批量更新模块到最新的时候就:
git submodule foreach git submodule update
若是像让你引入的第三方库leg
符合你本身的定制,你在里面发生了一些修改,可是这些修改并不能提交到远程去,由于你的提交会让第三方库的做者产生困扰:我写的好好的一个轮子你给定制成这样,还怎么去给其余的人用?
并且这个问题很严重,若是你本地的leg
和body
都更新了,可是 第三方的leg
不能提交到远程,而body
提交上去了,那么与你同使用一个版本库的小伙伴就会由于当前项目leg
的指针地址找不到而产生报错
因此若是有定制的须要就得去fork
这个项目到你本身的 github 上,而后本身想怎么折腾都随意了,可是怎么去既有定制,还能保持和轮子做者的版本同步呢?
首先是本身有一个 fork 的三方项目,而后在本身本地添加一个三方的源
cd path/to/body/leg ➜ leg git:(master) git remote -v origin https://git.oschina.net/gaofeifps/leg.git (fetch) origin https://git.oschina.net/gaofeifps/leg.git (push) #添加第三方包的源地址 ➜ leg git:(master) git remote add dist_source https://git.oschina.net/xxxx/leg.git ➜ leg git:(master) git remote -v dist_source https://git.oschina.net/xxxx/leg.git (fetch) #这个是三方的源地址 dist_source https://git.oschina.net/xxxx/leg.git (push) origin https://git.oschina.net/gaofeifps/leg.git (fetch) #这个是你 fork 的项目地址 origin https://git.oschina.net/gaofeifps/leg.git (push)
这样的话能够拉取源文件到本地并合并本地代码
git pull dist_source master
修复一下版本冲突的文件,确认没有问题以后提交到本身 fork 的库中
git push origin master
这样其余人就能正常使用了
写了这么多突然发现:仍是复制粘贴比较省事啊!
那么
在当前 git 版本1.7.8
以前,删除指定的 submodule 的命令是
git rm <submodule-name>
在新版的 git 下,则是运行如下命令
git submodule deinit <submodule-name>
查看本地有哪些三方模块能够查看 .gitmodules
➜ body git:(master) cat .gitmodules [submodule "leg"] path = leg url = https://git.oschina.net/gaofeifps/leg.git