關於 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

原文地址

相關文章
相關標籤/搜索