git submodule命令
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項目中導入library庫?
- library庫在其他的項目中被修改了可以更新到遠程的代碼庫中?
- 其他項目如何獲取到library庫最新的提交?
- 如何在clone的時候能夠自動導入library庫?
解決以上問題,可以考慮使用git的 submodule 來解決。
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'