git submodule
命令用於初始化,更新或檢查子模組。
使用語法
git submodule [--quiet] add [<options>] [--] <repository> [<path>]
git submodule [--quiet] status [--cached] [--recursive] [--] [<path>…?]
git submodule [--quiet] init [--] [<path>…?]
git submodule [--quiet] deinit [-f|--force] (--all|[--] <path>…?)
git submodule [--quiet] update [<options>] [--] [<path>…?]
git submodule [--quiet] summary [<options>] [--] [<path>…?]
git submodule [--quiet] foreach [--recursive] <command>
git submodule [--quiet] sync [--recursive] [--] [<path>…?]
git submodule [--quiet] absorbgitdirs [--] [<path>…?]
基於公司的專案會越來越多,常常需要提取一個公共的類庫提供給多個專案使用,但是這個library怎麼和git在一起方便管理呢?
我們需要解決下面幾個問題:
解決以上問題,可以考慮使用git的 submodule 來解決。
git submodule
是一個很好的多專案使用共同類庫的工具,它允許類庫專案做為repository,子專案做為一個單獨的git專案存在父專案中,子專案可以有自己的獨立的commit
,push
,pull
。而父專案以Submodule的形式包含子專案,父專案可以指定子專案header,父專案中會的提交資訊包含Submodule的資訊,再clone父專案的時候可以把Submodule初始化。
以下是一些範例 -
1.新增子模組
在本例中,我們將會新增一個名為 「DbConnector」 的庫。
$ git submodule add http://github.com/chaconinc/DbConnector
Cloning into 'DbConnector'...
remote: Counting objects: 11, done.
remote: Compressing objects: 100% (10/10), done.
remote: Total 11 (delta 0), reused 11 (delta 0)
Unpacking objects: 100% (11/11), done.
Checking connectivity... done.
預設情況下,子模組會將子專案放到一個與倉庫同名的目錄中,本例中是 「DbConnector」。 如果你想要放到其他地方,那麼可以在命令結尾新增一個不同的路徑。
如果這時執行 git status
,你會注意到幾個東西。
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitmodules
new file: DbConnector
首先應當注意到新的 .gitmodules
檔案。 該置檔案儲存了專案 URL 與已經拉取的本地目錄之間的對映:
$ cat .gitmodules
[submodule "DbConnector"]
path = DbConnector
url = http://github.com/chaconinc/DbConnector
如果有多個子模組,該檔案中就會有多條記錄。 要重點注意的是,該檔案也像 .gitignore
檔案一樣受到(通過)版本控制。 它會和該專案的其他部分一同被拉取推播。 這就是克隆該專案的人知道去哪獲得子模組的原因。
在 git status
輸出中列出的另一個是專案檔案夾記錄。 如果你執行 git diff
,會看到類似下面的資訊:
$ git diff --cached DbConnector
diff --git a/DbConnector b/DbConnector
new file mode 160000
index 0000000..c3f01dc
--- /dev/null
+++ b/DbConnector
@@ -0,0 +1 @@
+Subproject commit c3f01dc8862123d317dd46284b05b6892c7b29bc
雖然 DbConnector 是工作目錄中的一個子目錄,但 Git 還是會將它視作一個子模組。當你不在那個目錄中時,Git 並不會跟蹤它的內容, 而是將它看作該倉庫中的一個特殊提交。
如果你想看到更漂亮的差異輸出,可以給 git diff
傳遞 --submodule
選項。
$ git diff --cached --submodule
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..71fc376
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "DbConnector"]
+ path = DbConnector
+ url = http://github.com/chaconinc/DbConnector
Submodule DbConnector 0000000...c3f01dc (new submodule)
2.克隆含有子模組的專案
接下來我們將會克隆一個含有子模組的專案。 當你在克隆這樣的專案時,預設會包含該子模組目錄,但其中還沒有任何檔案:
$ git clone http://github.com/chaconinc/MainProject
Cloning into 'MainProject'...
remote: Counting objects: 14, done.
remote: Compressing objects: 100% (13/13), done.
remote: Total 14 (delta 1), reused 13 (delta 0)
Unpacking objects: 100% (14/14), done.
Checking connectivity... done.
$ cd MainProject
$ ls -la
total 16
drwxr-xr-x 9 schacon staff 306 Sep 17 15:21 .
drwxr-xr-x 7 schacon staff 238 Sep 17 15:21 ..
drwxr-xr-x 13 schacon staff 442 Sep 17 15:21 .git
-rw-r--r-- 1 schacon staff 92 Sep 17 15:21 .gitmodules
drwxr-xr-x 2 schacon staff 68 Sep 17 15:21 DbConnector
-rw-r--r-- 1 schacon staff 756 Sep 17 15:21 Makefile
drwxr-xr-x 3 schacon staff 102 Sep 17 15:21 includes
drwxr-xr-x 4 schacon staff 136 Sep 17 15:21 scripts
drwxr-xr-x 4 schacon staff 136 Sep 17 15:21 src
$ cd DbConnector/
$ ls
$
其中有 DbConnector 目錄,不過是空的。 你必須執行兩個命令:git submodule init 用來初始化本地組態檔案,而 git submodule update
則從該專案中抓取所有資料並檢出父專案中列出的合適的提交。
$ git submodule init
Submodule 'DbConnector' (http://github.com/chaconinc/DbConnector) registered for path 'DbConnector'
$ git submodule update
Cloning into 'DbConnector'...
remote: Counting objects: 11, done.
remote: Compressing objects: 100% (10/10), done.
remote: Total 11 (delta 0), reused 11 (delta 0)
Unpacking objects: 100% (11/11), done.
Checking connectivity... done.
Submodule path 'DbConnector': checked out 'c3f01dc8862123d317dd46284b05b6892c7b29bc'
現在 DbConnector 子目錄是處在和之前提交時相同的狀態了。
不過還有更簡單一點的方式。 如果給 git clone
命令傳遞 --recursive
選項,它就會自動初始化並更新倉庫中的每一個子模組。
$ git clone --recursive http://github.com/chaconinc/MainProject
Cloning into 'MainProject'...
remote: Counting objects: 14, done.
remote: Compressing objects: 100% (13/13), done.
remote: Total 14 (delta 1), reused 13 (delta 0)
Unpacking objects: 100% (14/14), done.
Checking connectivity... done.
Submodule 'DbConnector' (http://github.com/chaconinc/DbConnector) registered for path 'DbConnector'
Cloning into 'DbConnector'...
remote: Counting objects: 11, done.
remote: Compressing objects: 100% (10/10), done.
remote: Total 11 (delta 0), reused 11 (delta 0)
Unpacking objects: 100% (11/11), done.
Checking connectivity... done.
Submodule path 'DbConnector': checked out 'c3f01dc8862123d317dd46284b05b6892c7b29bc'
3. 刪除Submodule
git 並不支援直接刪除Submodule需要手動刪除對應的檔案:
cd pod-project
git rm --cached pod-library
rm -rf pod-library
rm .gitmodules
更改git的組態檔案config:
vim .git/config
可以看到Submodule的組態資訊:
[submodule "pod-library"]
url = [email protected]:jjz/pod-library.git
刪除submodule相關的內容,然後提交到遠端伺服器:
git commit -a -m 'remove pod-library submodule'