目錄
- 建立倉(cāng)庫(kù)
1.1 創(chuàng)建主倉(cāng)庫(kù)
1.2 創(chuàng)建子倉(cāng)庫(kù) - 提交內(nèi)容
2.1 提交到主工程的倉(cāng)庫(kù)
2.2 提交到子模塊的倉(cāng)庫(kù) - 克隆帶子模塊的倉(cāng)庫(kù)到本地
- 更新子倉(cāng)庫(kù)
- 總結(jié)
- 參考文檔
正文
軟件開(kāi)發(fā)中有一個(gè)DRY(Don't Repeat yourself)原則香拉,或者說(shuō)DIE(Duplication Is Evil)原則径密,指的是盡可能減少一切重復(fù)工作钳吟,重用一切可能重用的東西,小到提取重復(fù)性代碼鸳址,大到重用一個(gè)模塊。時(shí)間就是金錢(qián)泉懦,效率就是生命稿黍。
使用Git管理項(xiàng)目的時(shí)候,如果涉及到模塊重用崩哩,比如你需要用到別的倉(cāng)庫(kù)提供的功能巡球,雖然你可以直接把別人倉(cāng)庫(kù)(當(dāng)然也可以是自己的倉(cāng)庫(kù))的代碼復(fù)制到你的工程目錄下,但是這樣當(dāng)別的倉(cāng)庫(kù)更新了邓嘹,我們也想相應(yīng)的更新我們所依賴的代碼酣栈,或者我們對(duì)依賴的代碼做了些更改想要合并到原倉(cāng)庫(kù),這時(shí)候事情就比較麻煩了汹押。所以矿筝,我們希望主模塊和子模塊的的管理是分開(kāi)的,也就是主模塊的更改棚贾、提交等窖维,是不涉及子模塊的榆综,反過(guò)來(lái)子模塊也一樣。但是又希望他們之間有一個(gè)依賴關(guān)系铸史,怎么辦呢奖年?
Git為了這種困境提供了一個(gè)解決方案:子模塊(submodule)。
為了便于理解沛贪,我們把當(dāng)前工作工程倉(cāng)庫(kù)成為主倉(cāng)庫(kù)陋守,主倉(cāng)庫(kù)所依賴的子模塊倉(cāng)庫(kù)成為子倉(cāng)庫(kù)。
建立倉(cāng)庫(kù)
創(chuàng)建主倉(cāng)庫(kù)
mkdir demo && cd demo && git init
創(chuàng)建子倉(cāng)庫(kù)
創(chuàng)建子倉(cāng)庫(kù)用到的命令是git submodule add <repo> [<path>]
利赋。其中repo
是你要添加為子模塊的倉(cāng)庫(kù)URL水评,path
是主工程下的一個(gè)路徑,就相當(dāng)與你在主工程下創(chuàng)建的一個(gè)專(zhuān)門(mén)用于保存子倉(cāng)庫(kù)代碼的文件夾媚送,名字是任意的中燥,只不過(guò)習(xí)慣上用third_party
利于區(qū)分和理解。例如我們將pybind11添加為子模塊塘偎,其相對(duì)路徑為third_party/pybind11
疗涉,我們可以使用以下命令:
git submodule add https://github.com/pybind/pybind11 third_party/pybind11
值得注意的是,pybind11
這個(gè)目錄在在使用命令前是不能存在與third_party
目錄之下的吟秩。并且咱扣,此命令執(zhí)行完成以后,子倉(cāng)庫(kù)的代碼就被拉取到third_party/pybind11
之中了涵防。
提交內(nèi)容
主倉(cāng)庫(kù)和子倉(cāng)庫(kù)之間闹伪,除了子倉(cāng)庫(kù)位于主倉(cāng)庫(kù)內(nèi),主倉(cāng)庫(kù)對(duì)子倉(cāng)庫(kù)的代碼有所依賴以外壮池,他們之間是沒(méi)有其他任何聯(lián)系的偏瓤。他們呢就相當(dāng)于兩個(gè)倉(cāng)庫(kù),主倉(cāng)庫(kù)不會(huì)跟蹤子倉(cāng)庫(kù)內(nèi)容的變化椰憋,反過(guò)來(lái)子倉(cāng)庫(kù)也不去跟蹤子倉(cāng)庫(kù)的任何信息厅克。就類(lèi)似古代周邊某些附屬小國(guó),雖然名面上朝貢橙依、附屬证舟,但實(shí)際上小國(guó)的治理和天朝是分開(kāi)的。
提交到主工程的倉(cāng)庫(kù)
對(duì)主工程內(nèi)容的提交操作票编,與一般無(wú)子工程的倉(cāng)庫(kù)操作并無(wú)二致褪储。
提交到子模塊的倉(cāng)庫(kù)
如果有需要對(duì)子模塊的內(nèi)容進(jìn)行修改并提交到其倉(cāng)庫(kù),可以進(jìn)入到子模塊倉(cāng)庫(kù)所在目錄慧域,再進(jìn)行相應(yīng)的操作鲤竹。例如,我們使用cd third_party/pybind11
進(jìn)入到子模塊倉(cāng)庫(kù),這時(shí)候我們可以使用git add, git commit
等對(duì)更改進(jìn)行操作辛藻,這些操作之對(duì)子模塊倉(cāng)庫(kù)產(chǎn)生影響碘橘。
克隆帶子模塊的倉(cāng)庫(kù)到本地
當(dāng)我們需要克隆一個(gè)帶子倉(cāng)庫(kù)的倉(cāng)庫(kù)時(shí),我們希望子倉(cāng)庫(kù)的內(nèi)容也是跟主倉(cāng)庫(kù)一起保存在本地的吱肌。當(dāng)使用git clone xxxx.git
將主倉(cāng)庫(kù)克隆到本地后痘拆,子倉(cāng)庫(kù)所在目錄只有一個(gè)空目錄,子倉(cāng)庫(kù)內(nèi)容其實(shí)并為下載到本地氮墨。有兩種方法:
- 在克隆主倉(cāng)庫(kù)時(shí)加上
--recurse-submodules
纺蛆,使用這種方法,子倉(cāng)庫(kù)內(nèi)容也會(huì)同時(shí)下載下來(lái)规揪,如果子倉(cāng)庫(kù)還包含子倉(cāng)庫(kù)桥氏,也會(huì)被同時(shí)下載下來(lái)。
git clone xxxx.git --recurse-submodules
- 第二種方法是使用下面兩條命令:
git submodule init
git submodule update
值得注意的是猛铅,不管使用以上那兩種方法字支,子倉(cāng)庫(kù)的內(nèi)容雖然下載下來(lái)了,但是此時(shí)子倉(cāng)庫(kù)的狀態(tài)是處于一種HEAD detached
的狀態(tài)奸忽,也就是此時(shí)堕伪,你對(duì)子倉(cāng)庫(kù)的更改,就算你已經(jīng)commit
但是當(dāng)你下次使用git submodule update
你所作的更改也會(huì)丟失栗菜。所以欠雌,你學(xué)要checkout`到一個(gè)工作分支,例如:
git checkout master
更新子倉(cāng)庫(kù)
更新子倉(cāng)庫(kù)內(nèi)容有兩種方法苛萎,一種是進(jìn)入到子倉(cāng)庫(kù)所在目錄桨昙,進(jìn)行常規(guī)的拉取和合并操作检号;
cd ./third_party/pybind11
git fecth
git merge
另一種是使用git submodule update --remote
:
git submodule update --remote
git submodule update --remote <submodule ame>
兩條命令的區(qū)別是腌歉,如果不帶子倉(cāng)庫(kù)名,默認(rèn)會(huì)更新所有子倉(cāng)庫(kù)齐苛,如果只想更新其中某個(gè)翘盖,需要指定需要更新的子倉(cāng)庫(kù)名。
總結(jié)
對(duì)于帶子倉(cāng)庫(kù)的倉(cāng)庫(kù)凹蜂,有兩種情況:
- 本地新建倉(cāng)庫(kù)馍驯,需要建立與遠(yuǎn)程子倉(cāng)庫(kù)的依賴關(guān)系;
- 克隆已有帶子倉(cāng)庫(kù)的倉(cāng)庫(kù)到本地玛痊。
第一種情況:
git submodule add <repo> [<path>]
第二種情況:
git submodule init [<path>]
git submodule update
git checkout <branch>
至此汰瘫,依賴關(guān)系建立起來(lái)了,兩個(gè)倉(cāng)庫(kù)之間便可以獨(dú)自操作擂煞。
可以使用git add
, git commit
, git status
等各自操作混弥。一句話,說(shuō)的底盤(pán)聽(tīng)水的:在主倉(cāng)庫(kù)目錄下对省,操作的是主倉(cāng)庫(kù)內(nèi)容蝗拿;cd third_party/sumdir
進(jìn)入到子倉(cāng)庫(kù)晾捏,操作的便是子倉(cāng)庫(kù)內(nèi)容。
References
- Git-Tools-Submodules
- Manual: man git submodule