合作開(kāi)發(fā),不得不使用git來(lái)進(jìn)行項(xiàng)目管理峦筒,下面來(lái)記錄下關(guān)于git的踩坑記錄。
子模塊概念
對(duì)于一些比較大的工程窗慎,為了便模塊復(fù)用物喷,常常需要抽取子項(xiàng)目卤材,分布式管理項(xiàng)目依賴(lài),會(huì)用到子模塊(git submodule
)峦失。
子模塊跟父工程之間是兩個(gè)獨(dú)立的git
倉(cāng)庫(kù)扇丛,只是父工程存儲(chǔ)了它依賴(lài)的子倉(cāng)庫(kù)的版本號(hào)信息而已,信息提交相互獨(dú)立尉辑。
子模塊創(chuàng)建
子模塊添加
# 在主工程倉(cāng)庫(kù)中添加子依賴(lài)子模塊
$ git submodule add <遠(yuǎn)程子模塊倉(cāng)庫(kù)地址> <相對(duì)于項(xiàng)目的本地路徑>
下面模擬添加帆精,執(zhí)行完添加之后會(huì)返現(xiàn)本地多了一個(gè).gitmodules
隱藏文件。
$ git submodule add https://github.com/xxx/module.git module
$ cat .gitmodules
[submodule "module"]
path = module
url = https://github.com/xxx/module.git
設(shè)置子模塊依賴(lài)分支
$ git submodule set-branch (--branch|-b <branch>) [--] <path>
# 例如設(shè)置 module 子模塊依賴(lài)分支為 develop
$ git submodule set-branch -b develop module
$ cat .gitmodules
[submodule "module"]
path = module
url = https://github.com/xxx/module.git
branch = develop
查看.gitmodules
文件發(fā)現(xiàn)其指定了一個(gè)依賴(lài)的子模塊隧魄,path
指明在主倉(cāng)庫(kù)的位置卓练,url
指明子模塊倉(cāng)庫(kù)的遠(yuǎn)程地址。
并且在主工程倉(cāng)庫(kù)的.git/config
配置文件中加入了submodule
字段
[submodule "module"]
url = https://github.com/xxx/module.git
active = true
clone帶有子模塊的倉(cāng)庫(kù)
在主工程倉(cāng)庫(kù)添加完子模塊并push
到遠(yuǎn)端之后堤器,同事需要clone
或者pull
主工程倉(cāng)庫(kù)之后昆庇,會(huì)發(fā)現(xiàn)子模塊依賴(lài)信息(有.gitmodules
文件),但是子模塊文件目錄下面是空的闸溃,這個(gè)時(shí)候需要手動(dòng)對(duì)子模塊信息初始化并更新整吆。
$ git submodule init
# 執(zhí)行結(jié)果
Submodule 'module' (https://github.com/xxxx/module.git) registered for path 'module'
補(bǔ)充:當(dāng)有該倉(cāng)庫(kù)下依賴(lài)了多個(gè)子模塊,但是只想初始化指定的子模塊辉川,可以在指令后面追加需要初始化模塊path
$ git submodule init [<path>…]
# 例如 git submodule init demo1 demo2
這時(shí).git/config
配置文件中會(huì)包含有依賴(lài)的子模塊信息表蝙,再執(zhí)行更新,從遠(yuǎn)程拉取依賴(lài)的commit id
子模塊代碼
git submodule update
# 執(zhí)行結(jié)果
Cloning into '/.../MainProject/module'...
Submodule path 'module': checked out 'submodule commit id'
當(dāng)多層依賴(lài)子模塊時(shí)(子模塊里面依賴(lài)有子模塊)乓旗,這個(gè)時(shí)候就比較麻煩了府蛇,每次clone
下來(lái)之后首先要在第一層依賴(lài)的子模塊的倉(cāng)庫(kù)對(duì)子模塊進(jìn)行init
和update
,之后再進(jìn)入依賴(lài)有子模塊的子模塊倉(cāng)庫(kù)再進(jìn)行init
和update
屿愚,以此遞歸下去汇跨,比較麻煩,此時(shí)可以使用下面指令一次性完成遞歸init
和update
$ git submodule update --init --recursive
也或者直接在clone
的時(shí)候完成多層依賴(lài)的子模塊們的init
和update
$ git clone --recurse-submodules <遠(yuǎn)程主工程倉(cāng)庫(kù)地址>
這樣便省去了手動(dòng)遞歸執(zhí)行$ git submodule init
和$ git submodule update
注意:不管是使用系統(tǒng)的遞歸克隆還是手動(dòng)遞歸執(zhí)行的初始化和更新妆距,此時(shí)子模塊的HEAD都有可能處于游離狀態(tài)穷遂,需要手動(dòng)切換到對(duì)應(yīng)的分支
子模塊信息更改
主工程都記錄有依賴(lài)的子工程的提交版本,查看主工程依賴(lài)的commit id
$ git submodule status
# 結(jié)果
414b65085b41f4270322716df924625fdbcedf7b module (heads/master)
我們可以cd
到子工程倉(cāng)庫(kù)目錄下面娱据,對(duì)子工模塊代碼做一些修改蚪黑,在commit
之前主倉(cāng)庫(kù)status
會(huì)顯示module modified content
,顯示子模塊原先提交版本上有臟數(shù)據(jù)中剩;在commit
之后主倉(cāng)庫(kù)的status
會(huì)顯示module new commits
忌穿,依賴(lài)的子模塊的提交版本號(hào)發(fā)生變化,在子模塊倉(cāng)庫(kù)代碼提交并更新到遠(yuǎn)端之后结啼,便可以提交更新依賴(lài)的子模塊的提交版本號(hào)掠剑。
注意:主工程的提交及更新并不會(huì)對(duì)子模塊代碼造成影響,只會(huì)影響其依賴(lài)的子模塊提交版本
如果同事更新了子模塊代碼郊愧,然后更新了父項(xiàng)目中依賴(lài)的版本號(hào)朴译。你在主倉(cāng)庫(kù)執(zhí)行git pull
之后會(huì)發(fā)現(xiàn)子模塊文件有變更沸伏,執(zhí)行git diff
會(huì)發(fā)現(xiàn)如下更改
$ git diff
-Subproject commit f88b46fefb73438e2e65c2b7bc7baba8a64ae5d2 #同事新提交的子模塊版本
+Subproject commit c577a495c14159b3693c54af2a0bb9760d748246 #我們?cè)瓉?lái)依賴(lài)的子模塊的老版本
這時(shí)我們?nèi)绻麑?duì)父工程倉(cāng)庫(kù)代碼直接進(jìn)行提交,便會(huì)更改父?jìng)}庫(kù)依賴(lài)的子模塊版本號(hào)动分,別人更新下來(lái)的父?jìng)}庫(kù)還是依賴(lài)?yán)系淖幽K提交版本毅糟。雖然后期可以通過(guò)更新依賴(lài)版本更正過(guò)來(lái),但是也會(huì)給平時(shí)的合作開(kāi)發(fā)帶來(lái)不必要的麻煩澜公,因此每次對(duì)主倉(cāng)庫(kù)進(jìn)行git pull
之后姆另,還要執(zhí)行git submodule update
對(duì)依賴(lài)的子模塊代碼進(jìn)行一次更新。
但是如果子模塊里面還依賴(lài)有子模塊坟乾,我們就需要cd到對(duì)應(yīng)的目錄下面迹辐,一層層調(diào)用子模塊更新,此時(shí)為了方便甚侣,我們可以用git submodule update --recursive
指令完成多層子模塊代碼的更新明吩。
子模塊刪除
刪除一共分為3步
1、從.git/config
中刪除子模塊條目
$ git submodule deinit -f <path>
# 例如:想刪除名字叫 module 的子模塊
$ git submodule deinit -f module
2殷费、從.git/modules
目錄中刪除子模塊目錄
$ rm -rf .git/modules/<path>
# 例如:想刪除名字叫 module 的子模塊
$ rm -rf .git/modules/module
3印荔、刪除.gitmodules
中子模塊條目,并刪除項(xiàng)目目錄下的子模塊目錄
$ git rm -f <path>
# 例如:想刪除名字叫 module 的子模塊
$ git rm -f module