关于 git-submodule 的一些基本操做

项目中常常会使用到第三方的 git 库,将三方库整合到项目中最简单的办法就是复制粘贴,可是若是这个库升级了一个很酷炫的功能,你要怎么整合进来呢?(其实就是 git 版的包管理器)git

这就是本次要介绍的 git-submodule 操做,直接把第三方的版本库合并到本身的库中.github

添加第三方库

我这里是本身开了两个库作测试,主库叫 body,另外一个库叫 leg测试

首先在本地的body库中添加legfetch

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符合你本身的定制,你在里面发生了一些修改,可是这些修改并不能提交到远程去,由于你的提交会让第三方库的做者产生困扰:我写的好好的一个轮子你给定制成这样,还怎么去给其余的人用?

并且这个问题很严重,若是你本地的legbody都更新了,可是 第三方的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

这样其余人就能正常使用了

写了这么多突然发现:仍是复制粘贴比较省事啊!

那么

怎么删除submodule?

在当前 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

原文地址

相关文章
相关标签/搜索