設定與組態
取得與建立專案
基本快照
分支與合併
分享與更新專案
檢查與比較
修補
除錯
電子郵件
外部系統
伺服器管理
指南
- gitattributes
- 命令列介面規範
- Git 日常使用
- 常見問題 (FAQ)
- 詞彙表
- 掛鉤 (Hooks)
- gitignore
- gitmodules
- 修訂版本 (Revisions)
- 子模組
- 教學
- 工作流程
- 所有指南...
管理
底層命令 (Plumbing Commands)
- 2.53.0 → 2.55.0 無變更
-
2.52.0
2025-11-17
- 2.44.1 → 2.51.2 無變更
-
2.44.0
2024-02-23
- 2.43.1 → 2.43.7 無變更
-
2.43.0
2023-11-20
- 2.35.1 → 2.42.4 無變更
-
2.35.0
2022-01-24
- 2.29.1 → 2.34.8 無變更
-
2.29.0
2020-10-19
- 2.27.1 → 2.28.1 無變更
-
2.27.0
2020-06-01
- 2.25.1 → 2.26.3 無變更
-
2.25.0
2020-01-13
- 2.22.1 → 2.24.4 無變更
-
2.22.0
2019-06-07
- 2.19.3 → 2.21.4 無變更
-
2.19.2
2018-11-21
- 2.19.1 無變更
-
2.19.0
2018-09-10
- 2.17.0 → 2.18.5 無變更
-
2.16.6
2019-12-06
- 2.15.4 無變更
-
2.14.6
2019-12-06
描述
子模組(submodule)是嵌入在另一個儲存庫中的儲存庫。子模組擁有自己的歷史記錄;而嵌入它的儲存庫則被稱為父專案(superproject)。
在檔案系統上,子模組通常(但非總是 - 請參見下方的「形式」)由以下部分組成:(i) 位於父專案 $GIT_DIR/modules/ 目錄下的 Git 目錄,(ii) 位於父專案工作目錄內的工作目錄,以及 (iii) 位於子模組工作目錄根目錄下,指向 (i) 的 .git 檔案。
假設子模組在 $GIT_DIR/modules/foo/ 有一個 Git 目錄,且在 path/to/bar/ 有一個工作目錄,父專案會透過樹狀結構中位於 path/to/bar 的 gitlink 項目,以及其 .gitmodules 檔案(參見 gitmodules[5])中格式為 submodule.foo.path = path/to/bar 的項目來追蹤該子模組。
gitlink 項目包含了父專案預期子模組工作目錄所在的提交物件名稱。
.gitmodules 檔案中的 submodule.foo.* 區段為 Git 的 porcelain 層提供了額外的提示。例如,submodule.foo.url 設定指定了從何處獲取該子模組。
子模組至少可用於兩種不同的使用場景:
-
使用另一個專案同時保持獨立的歷史記錄。子模組允許您將另一個專案的工作樹包含在您自己的工作樹中,同時保持兩個專案的歷史記錄分開。此外,由於子模組被固定在特定的版本,另一個專案可以在不影響父專案的情況下獨立開發,這使得父專案僅在需要時才將自身鎖定到新版本。
-
將(邏輯上單一的)專案拆分為多個儲存庫並將它們重新連結在一起。這可用於克服 Git 現有實作限制,以實現更細粒度的存取控制:
-
Git 儲存庫的大小:以目前的格式,Git 對於大型儲存庫的擴展性較差,特別是包含未透過樹狀結構間的增量運算壓縮的內容時。例如,您可以使用子模組來儲存大型二進位資產,並且這些儲存庫可以進行淺層複製(shallow clone),這樣您在本地就不會擁有龐大的歷史記錄。
-
傳輸大小:以目前的格式,Git 要求必須存在整個工作樹。它不允許在 fetch 或 clone 時傳輸部分樹。如果您工作所在的專案由多個以子模組形式連結在父專案中的儲存庫組成,您可以避免獲取您不感興趣的儲存庫工作樹。
-
存取控制:透過限制使用者對子模組的存取,可用於為不同使用者實作讀/寫策略。
-
子模組的設定
子模組的操作可以使用以下機制進行設定(按優先權從高到低排列):
-
命令列:適用於那些支援將子模組作為路徑規格(pathspec)一部分的命令。大多數命令都有一個布林旗標
--recurse-submodules,指定是否遞迴進入子模組。例如grep和checkout。有些命令接受列舉值(enum),例如fetch和push,您可以在其中指定子模組如何受到影響。 -
子模組內部的設定。這包括子模組中的
$GIT_DIR/config,但也包括樹中的設定,例如指定子模組內部命令行為的.gitattributes或.gitignore檔案。例如,當您在父專案中執行
gitstatus--ignore-submodules=none時,會觀察到子模組.gitignore檔案的效果。它會透過在子模組中執行status來收集子模組工作目錄的資訊,同時注意子模組的.gitignore檔案。當在父專案中執行
gitpush--recurse-submodules=check時,子模組的$GIT_DIR/config檔案會發揮作用,因為這會檢查子模組是否有任何未推送到遠端的變更。遠端儲存庫通常是在子模組的$GIT_DIR/config檔案中設定。 -
父專案中的
$GIT_DIR/config設定檔。Git 僅會遞迴進入活躍子模組(參見下方的「活躍子模組」章節)。如果子模組尚未初始化,則子模組內部的設定尚不存在,因此這裡設定了例如從何處獲取該子模組。
-
父專案內的
.gitmodules檔案。專案通常使用此檔案來建議上游儲存庫集合的預設值,以對應子模組名稱與其路徑之間的關係。此檔案主要用作父專案中子模組名稱與路徑之間的對應,以便定位子模組的 Git 目錄。
如果子模組從未被初始化,這是唯一能找到子模組設定的地方。它作為最後的備用方案,指定從何處獲取該子模組。
形式
子模組可以採取以下形式:
-
「說明」一節中描述的基本形式:具有 Git 目錄、工作目錄、
gitlink以及.gitmodules項目。 -
「舊形式」子模組:一個帶有嵌入式
.git目錄的工作目錄,以及父專案中的追蹤gitlink和.gitmodules項目。這通常見於使用舊版 Git 生成的儲存庫。可以手動建構這些舊形式的儲存庫。
當取消初始化或刪除(見下文)時,子模組的 Git 目錄會自動移動到父專案的
$GIT_DIR/modules/<name>/。 -
已取消初始化的子模組:具有
gitlink和.gitmodules項目,但沒有子模組工作目錄。子模組的 Git 目錄可能依然存在,因為取消初始化後 Git 目錄會被保留。本應是工作目錄的目錄則是空的。執行
gitsubmoduledeinit可以取消初始化子模組。除了清空工作目錄外,該命令僅修改父專案的$GIT_DIR/config檔案,因此父專案的歷史記錄不受影響。這可以透過gitsubmoduleinit復原。 -
已刪除的子模組:執行 git rm <submodule-path> && git commit 可以刪除子模組。這可以透過
gitrevert復原。刪除操作會移除父專案的追蹤資料,即
gitlink項目和.gitmodules檔案中的區段。子模組的工作目錄會從檔案系統中移除,但 Git 目錄會被保留,以便在不需要從另一個儲存庫獲取的情況下,檢查過去的提交。要完全移除子模組,請手動刪除
$GIT_DIR/modules/<name>/。
活躍子模組
若符合以下情況,子模組被視為活躍:
-
若
submodule.<name>.active設為true或是
-
若子模組的路徑符合
submodule.active中的路徑規格或是
-
若已設定
submodule.<name>.url。
且這些項目會按此順序進行評估。
例如:
[submodule "foo"] active = false url = https://example.org/foo [submodule "bar"] active = true url = https://example.org/bar [submodule "baz"] url = https://example.org/baz
在上述設定中,只有子模組 bar 和 baz 是活躍的,bar 是因為 (1),baz 是因為 (3)。foo 不活躍,因為 (1) 的優先權高於 (3)。
注意,(3) 是歷史遺留產物,如果 (1) 和 (2) 指定子模組不活躍,它將會被忽略。換句話說,如果我們將 submodule.<name>.active 設為 false,或者如果子模組的路徑被排除在 submodule.active 的路徑規格之外,那麼 url 是否存在並不重要。這在接下來的範例中有所說明。
[submodule "foo"] active = true url = https://example.org/foo [submodule "bar"] url = https://example.org/bar [submodule "baz"] url = https://example.org/baz [submodule "bob"] ignore = true [submodule] active = b* active = :(exclude) baz
在此,除了 baz 之外的所有子模組(foo, bar, bob)都是活躍的。foo 是因為它自己的 active 旗標,而其他所有子模組是因為子模組的 active 路徑規格,它指定了任何以 b 開頭但不包含 baz 的子模組也是活躍的,無論是否存在 .url 欄位。
第三方函式庫的工作流程
# Add a submodule git submodule add <URL> <path>
# Occasionally update the submodule to a new version: git -C <path> checkout <new-version> git add <path> git commit -m "update submodule to new version"
# See the list of submodules in a superproject git submodule status
# See FORMS on removing submodules
人為拆分儲存庫的工作流程
# Enable recursion for relevant commands, such that # regular commands recurse into submodules by default git config --global submodule.recurse true
# Unlike most other commands below, clone still needs # its own recurse flag: git clone --recurse <URL> <directory> cd <directory>
# Get to know the code: git grep foo git ls-files --recurse-submodules
|
注意
|
git ls-files 也需要它自己的 --recurse-submodules 旗標。 |
# Get new code git fetch git pull --rebase
# Change worktree git checkout git reset
實作細節
當 clone 或 pull 包含子模組的儲存庫時,子模組預設不會被簽出(checked out);您可以指示 clone 遞迴進入子模組。git submodule 的 init 和 update 子命令將保持子模組在您的工作樹中處於簽出狀態並位於適當的修訂版本。或者,您可以設定 submodule.recurse,讓 checkout 遞迴進入子模組(注意 submodule.recurse 也會影響其他 Git 命令,請參見 git-config[1] 以獲得完整清單)。
GIT
git[1] 套件的一部分