Git的submodule功能詳解
git的submodule功能詳解
1. 前言
項目的版本庫在某些情況下需要引用其他版本庫中的文件,例如有一套公用的代碼庫,可以被多個項目調用,這個公用代碼庫能直接放在某個項目的代碼中,而是要獨立為一個代碼庫,那么其他要調用公用的代碼庫該如何處理?分別把公用的代碼庫拷貝到各自的項目中會造成冗余,丟棄了公共代碼庫的維護歷史,這些顯示不是好的辦法,現在要了解的git子模組(git submodule)就解決了這個問題。
Git 子模塊功能允許你將一個Git倉庫當作另外一個Git倉庫的子目錄。這允許你克隆另外一個倉庫到你的項目中并且保持你的提交相對獨立。
2. 準備工作
首先需要兩個版本庫例如:
1) 一個公共的版本庫(例如:libA.git)
git@gitlab.szreach.com:fengyang/liba.git
2) 一個引用公共版本庫的主版本庫(例如:super.git)
git@gitlab.szreach.com:fengyang/super.git
3. TortoiseGit上git submodule功能實現
1. 添加子模組的步驟
第一步:使用submodule add...添加子模組
在需要作添加子模組的Git版本庫中右擊,選擇“TortoiseGit->Submodule Add...”,在“Repository:”里面輸入需要添加子模組的版本庫路徑,在“Path:”
中輸入添加子模組存放的目錄路徑。如下圖所示:
|
|
此時查看需要添加子模組的Git工作區的目錄結構。在根目錄下多了一個.gitmodules文件,并且公共代碼庫被克隆到lib/lib_a目錄下。
|
|
第二步:查看.gitmodules的內容
.gitmodules的內容記錄著含子模組存放的目錄路徑及子模組版本庫的路徑
|
|
注:此時工作區尚未提交,完成提交后,子模組才算正式完成在需要作添加子模組的Git版本庫中創立。
注:此主版本庫(super.git)就變成了一個包含子模組的版本庫。
2. 克隆帶子模組的版本庫的步驟
克隆帶子模組的git庫,并不能自動將子模組的版本庫克隆出來,對于只關心項目本身的數據,而不關心項目引用的外部項目數據的用戶,這個功能非常好,數據沒有冗余而且克隆的速度也很快。
第一步:克隆super主版本庫
在工作區中克隆主主版本庫后,會發現子模組的版本庫并沒有克隆,只有將存放子模組版本庫的目錄克隆下來了。
|
|
|
|
第二步:克隆子模組
如果需要克隆出子模組形式引用的外部庫,首先需要執行Submodule Update操作。
在需要作克隆子模組的Git工作區中右擊,選擇“TortoiseGit->Submodule Update...”,點擊“OK”即可。
|
|
執行Submodule Update...操作后就會把子模組的版本庫克隆下來。
|
|
3. 對主Git庫工作區作commit、checkout、revert、pull、push等更改Git工作區內容的操作時,查看Submodule目錄下內容的效果
1) 對主Git庫工作區作commit操作
當在主Git庫工作區中變更到達一個適當狀態時,我們需要將這些變更提交到Git庫,作版本備份和跟蹤。
方法:
在工作區內右擊,選擇“ Commit-> "當前分支名稱" ”,在Commit窗口中,選擇需要提交的變更path,填寫提交說明,點擊“Ok”。
|
|
結論:在主git工作區作commit操作,只是將主Git工作區的變更歷史提交到主Git本地庫中,對Submodule沒有任何影響。
2) 對主Git庫工作區作checkout操作
當在主Git庫工作區中想要切換到其他某個分支、某個tag、某個commit歷史記錄。
我們這里舉個特殊的例子:
切換到某個commit歷史記錄(如在主版本庫中提交子版本庫的歷史記錄)
方法:
在Git工作區內的某目錄上右擊,選擇“Swicht/Checkout...”在Swicht/Checkout...Checkout窗口中,在Switch to Commmit中列出需要切換的commit歷史記錄,在此列表中選擇需要切換到的commit歷史記錄,以后點擊“Ok”按鈕。
|
|
|
|
注:由于切換到的是在主版本庫中提交子版本庫的那條歷史記錄,因此子模組中狀態也會改換,也需要在子模組中執行切換。
執行Submodule Update操作即可。
|
|
3) 對主Git庫工作區作revert操作
當在主Git庫工作區中這次變更有錯誤時,就可以使用revert操作來撤銷這次次操作。
方法:
在工作區內右擊,選擇“Revert”,在Revert窗口中,選擇需要撤銷的變更path,點擊“Ok”。
|
|
|
|
結論:在主git工作區作revert操作,只是將主Git工作區某次的變更操作給撤銷,此次操作之前的commit都會被保留,且對Submodule沒有任何影響。
4) 對主Git庫工作區作push操作
當在主Git庫工作區中將主Git本地庫的數據推送到主Git遠程庫中。
方法:在工作區的目錄上(不要在文件上)右擊,選擇“Git Sync...”
"Local Branch","Remote Branch",“Remote URL”這3欄必須正確才能“推”數據。
|
|
結論:在主git工作區作push操作,只是將主Git本地庫的變更歷史推送到到主Git遠程庫中,對Submodule沒有任何影響。
5) 對主Git庫工作區作pull操作
當在主Git庫工作區中將主Git遠程庫的拉取到主Git本地庫中。
方法:在工作區的目錄上(不要在文件上)右擊,選擇“Git Sync...”
"Local Branch","Remote Branch",“Remote URL”這3欄必須正確才能“拉”數據。
|
|
結論:在主git工作區作pull操作,只是將主Git遠程庫的變更歷史拉取到到主Git本地庫中,對Submodule沒有任何影響。
4. 對submodule下的內容進行修改后commit、push,對submodule目錄作pull
在執行Submodule Update...操作更新出子模組后,都以某個具體的提交版本進行檢出,進入子模組目錄,會發現其處于非跟蹤狀態。
|
|
顯然這種情況下,如果修改lib/lib_a下的文件,提交就會丟失。下面介紹如何在檢查的子模組中修改,以及如何更新子模組。
在子模組中切換到master分支(或者其他想要修改的分支)后在進行修改。
l 切換到master分支,然后在工作區做一些改動。
|
|
l 執行commit后,并且推送到子模組庫中后。
l 回到主版本庫中。
在主版本庫中查看狀態,在主版本庫中可以看到子模組已修改,包含了更新的提交。
l 需要將修改提交在主版本庫中進行推送。
|
|
當子模組版本庫中有新的提交歷史記錄,就需要做pull操作來更新。
|
|
注:對子模組庫中做了pull操作,同時需要對調用子模組庫的主版本庫中也要做Pull操作。
如下圖所示:
|
|
注意:進入子模組目錄,會發現其處于非跟蹤狀態。顯然這種情況下,如果修改lib/lib_a下的文件,提交就會丟失。提示如下:
|
|
5. 移除Submodule
第一步:用Delete(keep local) 將目錄或文件命令從git的索引庫中移除子模塊目錄
方法:
在工作區內目錄或文件上右擊,選擇“Delete(keep local)”,在Delete窗口中,點擊“Remove”。
Delete(keep local)把目錄lib/從git的索引庫中移除,但是對目錄lib/本身并不進行任何操作。
因此需要徹底刪除。
第二步:刪除物理文件
第三步:刪除.gitmodule文件
第四步:刪除.git/config的submodule配置源文件
刪除如下圖所示紅框的部門
|
|
第五步:刪除后,提交更改
http://www.kafeitu.me/git/2012/03/27/git-submodule.html





















