簡體中文 ▾ 主題 ▾ 最新版本 ▾ git-gc 最後更新於 2.52.0

名稱

git-gc - 清理不必要的檔案並最佳化本地倉庫

概要

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

描述

在當前倉庫中執行一系列的維護任務,例如壓縮檔案修訂(以減少磁碟空間並提高效能)、刪除可能由先前呼叫git add建立的無法訪問的物件、打包引用、修剪引用日誌、rerere 元資料或過時的暫存區。還可能更新輔助索引,如提交圖 (commit-graph)。

當執行建立物件的常用外部命令時,它們會檢查自上次維護以來倉庫是否已大幅增長,如果增長則會自動執行 git gc。有關如何停用此行為,請參閱下面的 gc.auto

只有在不定期執行此類外部命令的情況下向倉庫新增物件、進行一次性倉庫最佳化、或例如清理不理想的大規模匯入時,才需要手動執行 git gc。有關匯入情況的更多詳細資訊,請參閱 git-fast-import[1] 的“PACKFILE OPTIMIZATION”部分。

選項

--aggressive

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

--auto

使用此選項,git gc 會檢查是否需要任何維護;如果不需要,它將退出而不執行任何工作。

有關此啟發式方法如何工作,請參閱下面的“CONFIGURATION”部分的 gc.auto 選項。

一旦透過超過 gc.autogc.autoPackLimit 等配置選項的限制觸發了維護,所有其他維護任務(例如 rerere、暫存區、引用日誌……)也將被執行。

--detach
--no-detach

如果系統支援,則在後臺執行。此選項將覆蓋 gc.autoDetach 配置。

--cruft
--no-cruft

在過期無法訪問物件時,將它們單獨打包到 cruft pack 中,而不是作為鬆散物件儲存。 --cruft 預設啟用。

--max-cruft-size=<n>

在將無法訪問的物件打包到 cruft pack 時,將新的 cruft pack 的大小限制在最多 <n> 位元組。將覆蓋透過 gc.maxCruftSize 配置指定的任何值。有關更多資訊,請參閱 git-repack[1]--max-cruft-size 選項。

--expire-to=<dir>

在將無法訪問的物件打包到 cruft pack 時,將包含已修剪物件(如果有)的 cruft pack 寫入目錄 <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

除了最大的非 cruft pack、任何帶有 .keep 檔案的 pack 以及任何 cruft pack(s) 之外,所有 pack 都會被合併到一個 pack 中。使用此選項時,將忽略 gc.bigPackThreshold

AGGRESSIVE

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

這些最佳化的效果大部分是持久的,例如,當 pack 和鬆散物件合併到另一個 pack 時,該 pack 中現有的 delta 可能會被重用,但在某些情況下,我們可能會從較新的 pack 中選擇一個次優的 delta。

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

在對給定倉庫執行定製的效能基準測試之前,使用此選項可能不值得。它花費的時間更長,並且產生的空間/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 檔案標記的 pack 時,git gc --auto 會將它們合併為一個更大的 pack。預設值為 50。將其設定為 0 將停用它。將 gc.auto 設定為 0 也會停用此項。

參閱下面的 gc.bigPackThreshold 配置變數。當使用時,它將影響自動 pack 限制的工作方式。

gc.autoDetach

使 git gc --auto 立即返回並在系統支援的情況下在後臺執行。預設值為 true。此配置變數充當回退,以防 maintenance.autoDetach 未設定。

gc.bigPackThreshold

如果非零,則在執行 git gc 時,所有大於此限制的非 cruft pack 都將被保留。這與 --keep-largest-pack 非常相似,只是所有符合閾值的非 cruft pack 都被保留,而不僅僅是最大的 pack。預設為零。支援 kmg 的常用單位字尾。

請注意,如果保留的 pack 數量超過 gc.autoPackLimit,則將忽略此配置變數,除了基本 pack 之外的所有 pack 都將重新打包。之後,pack 的數量應低於 gc.autoPackLimit,並且將再次尊重 gc.bigPackThreshold。

如果估計的 git repack 順利執行所需的記憶體量不可用且未設定 gc.bigPackThreshold,那麼最大的 pack 也將被排除(這相當於使用 --keep-largest-pack 執行 git gc)。

gc.writeCommitGraph

如果為 true,則 gc 在 git-gc[1] 執行時將重寫 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 會使其被 Git 版本早於 1.5.1.2 的透過啞傳輸(如 HTTP)克隆。此變數決定 git gc 是否執行 git pack-refs。可以將其設定為 notbare 以在所有非裸倉庫中啟用它,或者可以將其設定為布林值。預設值為 true

gc.cruftPacks

將無法訪問的物件儲存在 cruft pack 中(請參閱 git-repack[1]),而不是作為鬆散物件。預設值為 true

gc.maxCruftSize

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

gc.pruneExpire

當執行 git gc 時,它將呼叫 prune --expire 2.weeks.ago(如果使用 cruft pack(透過 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 會刪除早於此時間(預設為 90 天)的引用日誌條目。值“now”會立即過期所有條目,“never”會完全抑制過期。在中間使用“<pattern>”(例如“refs/stash”)時,設定僅適用於匹配 <pattern> 的引用。

gc.reflogExpireUnreachable
gc.<pattern>.reflogExpireUnreachable

git reflog expire 會刪除早於此時間且無法從當前尖端到達的引用日誌條目(預設為 30 天)。值“now”會立即過期所有條目,“never”會完全抑制過期。在中間使用“<pattern>”(例如“refs/stash”)時,設定僅適用於匹配 <pattern> 的引用。

這些型別的條目通常是使用 git commit --amendgit rebase 的結果,並且是發生在修改或 rebase 之前的提交。由於這些更改不是當前專案的一部分,大多數使用者希望更早地過期它們,因此預設設定比 gc.reflogExpire 更具侵略性。

gc.recentObjectsHook

在考慮是否刪除某個物件時(無論是生成 cruft pack 還是將無法訪問的物件儲存為鬆散物件),使用 shell 執行指定的命令。將其輸出解釋為 Git 將視為“最近”的物件 ID,無論其年齡如何。透過將它們的 mtime 視為“現在”,任何在輸出中提及的物件(及其後代)都將被保留,而不管其真實年齡。

輸出必須每行包含一個十六進位制物件 ID,並且別無其他。倉庫中找不到的物件將被忽略。支援多個 hook,但所有 hook 都必須成功退出,否則操作(生成 cruft pack 或解包無法訪問的物件)將中止。

gc.repackFilter

在重新打包時,使用指定的過濾器將某些物件移動到單獨的 packfile 中。請參閱 git-repack[1]--filter=<filter-spec> 選項。

gc.repackFilterTo

在重新打包並使用過濾器(請參閱 gc.repackFilter)時,指定的目錄將用於建立包含過濾掉的物件(即被過濾出去的物件)的 packfile。警告: 指定的目錄應可訪問,例如使用 Git 的 alternate 機制,否則 Git 可能會將倉庫視為已損壞,因為它可能無法訪問該 packfile 中的物件。請參閱 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 會盡最大努力不刪除在您的倉庫中任何地方被引用的物件。特別地,它不僅會保留由您當前分支和標籤集引用的物件,還會保留由索引、遠端跟蹤分支、引用日誌(可能引用後來被修改或回滾的分支中的提交)以及 refs/* 名稱空間中的任何其他內容引用的物件。請注意,附加到物件的註釋(由 git notes 建立的型別)不會影響物件的生命週期。如果您期望某些物件被刪除但未刪除,請檢查所有這些位置,並決定在您的場景下刪除這些引用是否有意義。

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

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

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

然而,這些功能並未提供完整的解決方案,因此併發執行命令的使用者必須承擔一定的損壞風險(儘管在實踐中風險似乎很低)。

鉤子

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

GIT

Git[1] 套件的一部分