English ▾ 主題 ▾ 最新版本 ▾ git-gc 最後更新於 2.52.0

名稱

git-gc - 清除不必要的檔案並最佳化本地儲存庫

概要

git gc [--aggressive] [--auto] [--[no-]detach] [--quiet] [--prune=<date> | --no-prune] [--force] [--keep-largest-pack]

描述

在當前儲存庫內執行一系列內務處理任務,例如壓縮檔案修訂版本(以減少磁碟空間並提高效能)、移除先前執行 git add 可能產生的無法存取物件、打包參照 (refs)、修剪參照日誌 (reflog)、rerere 中繼資料或過期的工作樹。也可能會更新輔助索引,例如 commit-graph。

當執行會建立物件的常見 Porcelain 指令時,它們會檢查儲存庫自上次維護以來是否已大幅增長,如果是,則會自動執行 git gc。請參閱下方的 gc.auto 以了解如何停用此行為。

手動執行 git gc 通常僅在以下情況需要:在不定期執行此類 Porcelain 指令的情況下向儲存庫添加物件、進行單次儲存庫最佳化,或例如清理次佳的大規模匯入。有關匯入案例的更多詳細資訊,請參閱 git-fast-import[1] 中的「PACKFILE OPTIMIZATION」章節。

選項

--aggressive

通常 git gc 執行速度很快,同時能提供良好的磁碟空間利用率和效能。此選項將使 git gc 以更積極的方式最佳化儲存庫,但代價是需要更多時間。此最佳化的效果大多是永久性的。詳細資訊請參閱下方的「AGGRESSIVE」章節。

--auto

使用此選項,git gc 會檢查是否需要進行任何內務處理;如果不需要,它將不執行任何工作直接退出。

請參閱下方「CONFIGURATION」章節中的 gc.auto 選項,了解此啟發式演算法是如何運作的。

一旦因超過 gc.autogc.autoPackLimit 等組態選項的限制而觸發內務處理,所有其他內務處理任務(例如 rerere、工作樹、reflog 等)也將一併執行。

--detach
--no-detach

如果系統支援,則在背景執行。此選項會覆寫 gc.autoDetach 組態。

--cruft
--no-cruft

當使無法存取的物件過期時,將它們單獨打包到一個殘餘包 (cruft pack) 中,而不是儲存為鬆散物件。預設開啟 --cruft

--max-cruft-size=<n>

將無法存取的物件打包到殘餘包時,將新殘餘包的大小限制為最多 <n> 位元組。覆寫透過 gc.maxCruftSize 組態指定的任何值。更多資訊請參閱 git-repack[1]--max-cruft-size 選項。

--expire-to=<dir>

當將無法存取的物件打包到殘餘包時,將包含已修剪物件(如果有的話)的殘餘包寫入目錄 <dir>。此選項僅在與 --cruft 一起使用時有效。更多資訊請參閱 git-repack[1]--expire-to 選項。

--prune=<date>

修剪比指定日期更舊的鬆散物件(預設為 2 週前,可透過組態變數 gc.pruneExpire 覆寫)。--prune=now 不管物件的存留時間直接修剪鬆散物件,如果其他處理程序正在同時寫入儲存庫,會增加損毀的風險;請參閱下方的「NOTES」。預設開啟 --prune。

--no-prune

不修剪任何鬆散物件。

--quiet

隱藏所有進度報告。

--force

強制 git gc 執行,即使此儲存庫上可能已有另一個 git gc 執行個體正在執行。

--keep-largest-pack

除最大的非殘餘包、任何標記有 .keep 檔案的包以及任何殘餘包之外的所有包,都會合併為一個包。使用此選項時,會忽略 gc.bigPackThreshold

積極模式 (AGGRESSIVE)

提供 --aggressive 選項時,git-repack[1] 將以 -f 旗標呼叫,該旗標會將 --no-reuse-delta 傳遞給 git-pack-objects[1]。這會丟棄任何現有的差異 (deltas) 並重新計算它們,代價是花費更多時間進行重新打包。

其效果大多是永久性的,例如,當包和鬆散物件合併到另一個包中時,該包中現有的差異可能會被重複使用,但也有多種情況是我們可能會從較新的包中選擇一個次佳的差異。

此外,提供 --aggressive 會調整傳遞給 git-repack[1]--depth--window 選項。請參閱下方的 gc.aggressiveDepthgc.aggressiveWindow 設定。透過使用更大的視窗大小,我們更有可能找到最佳的差異。

在未對給定儲存庫執行量身定做的效能基準測試的情況下,使用此選項通常不划算。它需要花費更多時間,產生的空間/差異最佳化結果也不一定值得。對於大多數使用者及其儲存庫而言,完全不使用此選項是正確的取捨。

組態設定 (CONFIGURATION)

本節中此行以下的內容是從 git-config[1] 文件中選擇性包含的。內容與該處找到的內容相同

gc.aggressiveDepth

git gc --aggressive 使用的差異壓縮演算法中的深度參數。預設值為 50,這也是未使用 --aggressive--depth 選項的預設值。

有關詳細資訊,請參閱 git-repack[1]--depth 選項的文件。

gc.aggressiveWindow

git gc --aggressive 使用的差異壓縮演算法中的視窗大小參數。預設值為 250,這比 --window 預設的 10 要積極得多。

有關詳細資訊,請參閱 git-repack[1]--window 選項的文件。

gc.auto

當儲存庫中的鬆散物件數量大約超過此數量時,git gc --auto 將會打包它們。某些 Porcelain 指令會使用此指令不時執行輕量級的垃圾收集。預設值為 6700。

將此設定為 0 不僅會停用基於鬆散物件數量的自動打包,還會停用 git gc --auto 為了判斷是否有工作要做而使用的任何其他啟發式方法,例如 gc.autoPackLimit

gc.autoPackLimit

當儲存庫中沒有標記為 *.keep 檔案的包超過此數量時,git gc --auto 會將它們合併成一個更大的包。預設值為 50。將此設為 0 可停用此功能。將 gc.auto 設為 0 也會停用此功能。

請參閱下方的 gc.bigPackThreshold 組態變數。使用時,它會影響自動打包限制的運作方式。

gc.autoDetach

如果系統支援,讓 git gc --auto 立即返回並在背景執行。預設為 true。如果未設定 maintenance.autoDetach,此組態變數將作為後備方案。

gc.bigPackThreshold

如果非零,執行 git gc 時,所有大於此限制的非殘餘包都會被保留。這與 --keep-largest-pack 非常相似,不同之處在於所有滿足閾值的非殘餘包都會被保留,而不僅僅是最大的包。預設為零。支援常見的 kmg 單位後綴。

請注意,如果保留的包數量超過 gc.autoPackLimit,則會忽略此組態變數,除基礎包外的所有包都將被重新打包。此後,包的數量應該會降至 gc.autoPackLimit 以下,並且再次遵守 gc.bigPackThreshold。

如果沒有足夠的記憶體供 git repack 順利執行,且未設定 gc.bigPackThreshold,最大的包也將被排除(這等同於執行帶有 --keep-largest-packgit gc)。

gc.writeCommitGraph

如果為 true,則執行 git-gc[1] 時 gc 會重寫 commit-graph 檔案。使用 git gc --auto 時,如果需要內務處理,commit-graph 也會更新。預設為 true。詳細資訊請參閱 git-commit-graph[1]

gc.logExpiry

如果存在 gc.log 檔案,則 git gc --auto 將列印其內容並以狀態碼 0 退出,而不是執行,除非該檔案的時間超過 gc.logExpiry。預設為「1.day」。有關指定其值的更多方式,請參閱 gc.pruneExpire

gc.packRefs

在儲存庫中執行 git pack-refs 會導致早於 1.5.1.2 的 Git 版本無法透過 HTTP 等啞傳輸協定 (dumb transports) 進行複製。此變數決定 git gc 是否執行 git pack-refs。這可以設定為 notbare 以在所有非裸儲存庫中啟用,或者可以設定為布林值。預設為 true

gc.cruftPacks

將無法存取的物件儲存在殘餘包(請參閱 git-repack[1])中,而不是儲存為鬆散物件。預設為 true

gc.maxCruftSize

重新打包時限制新殘餘包的大小。當與 --max-cruft-size 一起指定時,命令列選項優先。請參閱 git-repack[1]--max-cruft-size 選項。

gc.pruneExpire

執行 git gc 時,它將呼叫 prune --expire 2.weeks.ago(如果透過 gc.cruftPacks--cruft 使用殘餘包,則呼叫 repack --cruft --cruft-expiration 2.weeks.ago)。使用此組態變數覆寫寬限期。可以使用「now」值來停用此寬限期並始終立即修剪無法存取的物件,或者使用「never」來禁止修剪。此功能有助於防止 git gc 與另一個正在寫入儲存庫的處理程序同時執行時發生損毀;請參閱 git-gc[1] 的「NOTES」章節。

gc.worktreePruneExpire

執行 git gc 時,它會呼叫 git worktree prune --expire 3.months.ago。此組態變數可用於設定不同的寬限期。可以使用「now」值來停用寬限期並立即修剪 $GIT_DIR/worktrees,或者使用「never」來禁止修剪。

gc.reflogExpire
gc.<pattern>.reflogExpire

git reflog expire 會移除早於此時間的 reflog 條目;預設為 90 天。「now」值會立即使所有條目過期,「never」則完全禁止過期。若中間有「<pattern>」(例如「refs/stash」),該設定僅適用於符合該 <pattern> 的參照。

gc.reflogExpireUnreachable
gc.<pattern>.reflogExpireUnreachable

git reflog expire 會移除早於此時間且無法從當前頂端 (tip) 存取的 reflog 條目;預設為 30 天。「now」值會立即使所有條目過期,「never」則完全禁止過期。若中間有「<pattern>」(例如「refs/stash」),該設定僅適用於符合該 <pattern> 的參照。

這類條目通常是因使用 git commit --amendgit rebase 而產生的,且是在修正或變基 (rebase) 發生之前的提交。由於這些變更不是當前專案的一部分,大多數使用者會希望更早讓它們過期,這就是為什麼預設值比 gc.reflogExpire 更積極的原因。

gc.recentObjectsHook

在考慮是否移除物件時(無論是在產生殘餘包時還是將無法存取的物件儲存為鬆散物件時),請使用 shell 執行指定的指令。將其輸出解釋為 Git 將視為「近期」的物件 ID,無論其實際存留時間為何。透過將它們的 mtime 視為「現在」,輸出中提到的任何物件(及其後代)都將被保留,而不論其真實存留時間。

輸出必須包含每行一個十六進位物件 ID,且不含其他內容。儲存庫中找不到的物件將被忽略。支援多個 Hook,但所有 Hook 必須成功退出,否則該作業(產生殘餘包或解開無法存取的物件)將被終止。

gc.repackFilter

重新打包時,使用指定的篩選器將特定物件移動到單獨的包檔案中。請參閱 git-repack[1]--filter=<filter-spec> 選項。

gc.repackFilterTo

重新打包並使用篩選器時,請參閱 gc.repackFilter,指定的位置將用於建立包含已篩選出物件的包檔案。警告:指定的位置應該是可存取的(例如使用 Git 的 alternates 機制),否則 Git 可能會認為儲存庫已損毀,因為它可能無法存取該包檔案中的物件。請參閱 git-repack[1]--filter-to=<dir> 選項,以及 gitrepository-layout[5] 中的 objects/info/alternates 章節。

gc.rerereResolved

執行 git rerere gc 時,您先前解決的衝突合併記錄會保留這麼多天。您也可以使用更具可讀性的「1.month.ago」等。預設為 60 天。請參閱 git-rerere[1]

gc.rerereUnresolved

執行 git rerere gc 時,您尚未解決的衝突合併記錄會保留這麼多天。您也可以使用更具可讀性的「1.month.ago」等。預設為 15 天。請參閱 git-rerere[1]

注意事項

git gc 會盡力不刪除您儲存庫中任何地方參照的物件。特別是,它不僅會保留您當前分支和標籤集所參照的物件,還會保留索引、遠端追蹤分支、reflogs(可能參照了後來被修改或倒轉的分支中的提交),以及 refs/* 命名空間中的任何其他物件。請注意,附加到物件的註解(由 git notes 建立的那種)不會對保持該物件存活有所貢獻。如果您期望某些物件被刪除但它們沒有被刪除,請檢查所有這些位置,並決定在您的情況下移除這些參照是否合理。

另一方面,當 git gc 與另一個程序同時執行時,存在刪除另一個程序正在使用但尚未建立參照的物件的風險。這可能只會導致另一個程序失敗,或者如果另一個程序稍後對已刪除的物件添加了參照,則可能會損毀儲存庫。Git 有兩個顯著緩解此問題的功能:

  1. 任何修改時間比 --prune 日期更新的物件都會被保留,連同從它可達的所有內容。

  2. 大多數向資料庫添加物件的操作都會在物件已存在時更新其修改時間,以便上述 #1 適用。

然而,這些功能還不是一個完整的解決方案,因此同時執行指令的使用者必須承擔一些損毀風險(實際上這風險很低)。

HOOKS (鉤子)

git gc --auto 指令將執行 pre-auto-gc hook。有關更多資訊,請參閱 githooks[5]

GIT

git[1] 套件的一部分