有種情況我們經常會遇到:某個工作中的項目需要包含並使用另一個項目。 也許是第三方庫,或者你 獨立開發的,用於多個父項目的庫。 現在問題來了:你想要把它們當做兩個獨立的項目,同時又想在 一個項目中使用另一個。
Git 通過子模塊來解決這個問題。 子模塊允許你將一個 Git 倉庫作為另一個 Git 倉庫的子目錄。 它能讓你將另一個倉庫克隆到自己的項目中,同時還保持提交的獨立。
開始使用子模塊
git submodule add remotePath [localPath]
克隆含有子模塊的項目
git clone remotePath git submodule init # 初始化本地配置文件 git submodule update # 從該項目中抓取所有數據並檢出父項目中列出的合適的提交。
在包含子模塊的項目上工作
-
進入子模塊目錄中手動抓取與合並
- 進入子模塊目錄
git fetch
git merger origin/master
- 進入主倉庫目錄
-
直接在主倉庫里抓取與合並子模塊
git submodule update --remote
-
在子模塊上工作
當我們運行 git submodule update 從子模塊倉庫中抓取修改時,Git 將會獲得這些改動並 更新子目錄中的文件,但是會將子倉庫留在一個稱作 “游離的 HEAD” 的狀態。 這意味着沒有本 地工作分支(例如 “master”)跟蹤改動。 所以你做的任何改動都不會被跟蹤。
git checkout stable 進入子模塊並檢出相應的工作分支 git submodule update --remote 從上游拉取數據 git submodule update --remote --merge 從上游拉取數據並合並
-
發布子模塊改動
如果我們在主項目中提交並推送但並不推送子模塊上的改動,其他嘗試檢出我們修改的人會遇到 麻煩,因為他們無法得到依賴的子模塊改動。 那些改動只存在於我們本地的拷貝中。
為了確保這不會發生,你可以讓 Git 在推送到主項目前檢查所有子模塊是否已推送。 git push 命令接受可以設置為
check
或on-demand
的 --recurse-submodules 參數。 如果任何提交的子模塊改動沒有推送那么check
選項會直接使 push 操作失敗。-
提交主項目時自動檢測子模塊是否有未提交的改動
git push --recurse-submodules=check
-
提交主項目時,嘗試自動推送一改動的子模塊
git push --recurse-submodules=on-demand
-
子模塊技巧
- 子模塊遍歷
有一個 foreach 子模塊命令,它能在每一個子模塊中運行任意命令。 如果項目中包含了大量子模塊,這會非常有用。
- 有用的別名
你可能想為其中一些命令設置別名,因為它們可能會非常長而你又不能 設置選項作為它們的默認選項。
子模塊的問題
例如在有子模塊的項目中切換分支可能會造成麻煩。 如果你創建一個新分支, 在其中添加一個子模塊,之后切換到沒有該子模塊的分支上時,你仍然會有一個還未跟蹤的子模塊目錄。