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

名稱

git-gc - 清理不必要的文件並最佳化本地儲存庫

概要

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

描述

在目前的儲存庫中執行多個內部管理工作,例如壓縮檔案修訂版本(以減少磁碟空間並提高效能)、移除先前調用 git add 所建立的無法存取的物件、打包 refs、修剪 reflog、rerere 元數據或過時的工作樹。也可能會更新輔助索引,例如提交圖表。

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

只有在將物件新增至儲存庫而沒有定期執行此類瓷器命令、執行一次性的儲存庫最佳化,或者例如清理次佳的大量匯入時,才需要手動執行 git gc。有關匯入案例的更多詳細資訊,請參閱 git-fast-import[1] 中的「PACKFILE OPTIMIZATION」部分。

選項

--aggressive

通常 git gc 的執行速度很快,同時提供良好的磁碟空間使用率和效能。此選項會導致 git gc 更積極地最佳化儲存庫,但會花費更多時間。此最佳化的效果大多是持久的。有關詳細資訊,請參閱下方的「AGGRESSIVE」部分。

--auto

使用此選項,git gc 會檢查是否需要任何內部管理;如果不需要,則會退出而不執行任何工作。

請參閱下方「組態」部分中的 gc.auto 選項,了解此啟發式方法的工作原理。

一旦因超出 gc.autogc.autoPackLimit 等組態選項的限制而觸發內部管理,也會執行所有其他內部管理工作(例如 rerere、工作樹、reflog…)。

--[no-]detach

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

--[no-]cruft

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

--max-cruft-size=<n>

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

--prune=<date>

修剪早於 date 的鬆散物件(預設為 2 週前,可由組態變數 gc.pruneExpire 覆寫)。--prune=now 會修剪鬆散物件,而不考慮其存在時間,並且如果另一個程序同時寫入儲存庫,則會增加損壞的風險;請參閱下方的「NOTES」。預設開啟 --prune。

--no-prune

不要修剪任何鬆散物件。

--quiet

隱藏所有進度報告。

--force

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

--keep-largest-pack

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

AGGRESSIVE

當提供 --aggressive 選項時,會使用 -f 旗標調用 git-repack[1],這反過來會將 --no-reuse-delta 傳遞給 git-pack-objects[1]。這將會捨棄任何現有的 deltas 並重新計算它們,但會花費更多時間在重新打包上。

這樣做的影響大多是持久的,例如,當包和鬆散物件合併成另一個包時,該包中現有的 deltas 可能會被重複使用,但也有各種情況,我們可能會從較新的包中選擇次佳的 delta。

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

在未對其執行量身定制的效能基準測試的情況下,在給定的儲存庫上使用此選項可能不值得。它需要花費更多時間,且產生的空間/delta 最佳化可能值得或不值得。對於大多數使用者及其儲存庫,完全不使用此選項是正確的權衡。

組態

此部分中此行以下的每一項都從 git-config[1] 文件中選擇性地包含。內容與那裡找到的內容相同

gc.aggressiveDepth

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

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

gc.aggressiveWindow

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

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

gc.auto

當儲存庫中大約有超過此數量的鬆散物件時,git gc --auto 會將它們打包。某些瓷器命令會不時使用此命令來執行輕量型的垃圾收集。預設值為 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-pack 執行 git 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 將會列印其內容並以狀態零結束,而不是執行,除非該檔案的修改時間超過 gc.logExpiry。預設值為 "1.day"。有關指定其值的更多方式,請參閱 gc.pruneExpire

gc.packRefs

在儲存庫中執行 git pack-refs 會使 1.5.1.2 之前的 Git 版本無法透過 HTTP 等「笨」傳輸方式複製該儲存庫。此變數決定 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] 的「注意事項」章節。

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> 的 ref。

gc.reflogExpireUnreachable
gc.<pattern>.reflogExpireUnreachable

git reflog expire 會移除早於此時間且無法從目前頂端存取的 reflog 條目;預設為 30 天。值 "now" 會立即過期所有條目,而 "never" 會完全抑制過期。中間有 "<pattern>"(例如 "refs/stash")時,設定僅適用於符合 <pattern> 的 ref。

這些類型的條目通常是使用 git commit --amendgit rebase 的結果所建立的,並且是修改或重新定位發生之前的提交。由於這些變更不屬於目前專案的一部分,因此大多數使用者會希望更快地讓它們過期,這就是預設值比 gc.reflogExpire 更積極的原因。

gc.recentObjectsHook

當考慮是否移除物件時(無論是產生廢棄封包還是將無法存取的物件儲存為鬆散物件),請使用 shell 執行指定的命令。將其輸出解讀為物件 ID,Git 將其視為「最近」,無論其存在時間長短。透過將它們的修改時間視為「現在」,輸出中提及的任何物件(及其後代)都將被保留,無論它們的真實存在時間長短。

輸出必須每行恰好包含一個十六進位物件 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 會盡力不刪除儲存庫中任何位置引用的物件。特別是,它不僅會保留您目前的一組分支和標籤所引用的物件,還會保留索引、遠端追蹤分支、reflog(可能會引用稍後修改或回溯的分支中的提交)以及 refs/* 命名空間中的其他任何內容所引用的物件。請注意,附加到物件的註解(由 git notes 建立的類型)無助於保持物件存活。如果您預期某些物件被刪除但沒有被刪除,請檢查所有這些位置,並決定在您的情況下刪除這些引用是否有意義。

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

  1. 任何修改時間比 --prune 日期新的物件都會被保留,以及所有可從中存取的物件。

  2. 如果物件已存在,大多數將物件新增至資料庫的操作都會更新物件的修改時間,以便套用 #1。

但是,這些功能無法提供完整的解決方案,因此同時執行指令的使用者必須承受一些損壞風險(實際上似乎很低)。

HOOK

git gc --auto 指令會執行 pre-auto-gc hook。有關詳細資訊,請參閱 githooks[5]

GIT

屬於 git[1] 套件的一部分

scroll-to-top