項目中常常會使用到第三方的 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