簡體中文 ▾ 主題 ▾ 最新版本 ▾ git-maintenance 上次更新於 2.50.0

名稱

git-maintenance - 執行任務以最佳化 Git 倉庫資料

概要

git maintenance run [<options>]
git maintenance start [--scheduler=<scheduler>]
git maintenance (stop|register|unregister) [<options>]

描述

執行任務以最佳化 Git 倉庫資料,從而加快其他 Git 命令的速度並減少倉庫的儲存需求。

新增倉庫資料的 Git 命令,例如 git addgit fetch,都經過最佳化以提供響應迅速的使用者體驗。這些命令不會花費時間來最佳化 Git 資料,因為此類最佳化與倉庫的完整大小成比例,而這些使用者命令每次執行相對較小的操作。

git maintenance 命令為如何最佳化 Git 倉庫提供了靈活性。

子命令

run

執行一個或多個維護任務。如果指定了一個或多個 --task 選項,則這些任務將按指定順序執行。否則,任務由哪些 maintenance.<task>.enabled 配置選項為 true 來決定。預設情況下,只有 maintenance.gc.enabled 為 true。

start

開始在當前倉庫上執行維護。這會執行與 register 子命令相同的配置更新,然後更新後臺排程程式以每小時執行 git maintenance run --scheduled

stop

停止後臺維護計劃。當前倉庫不會從維護的倉庫列表中移除,以防以後重新啟動後臺維護。

register

初始化 Git 配置值,以便任何計劃的維護都將在該倉庫上執行。這會將倉庫新增到當前使用者的全域性配置中的 maintenance.repo 配置變數,或由 --config-file 選項指定的配置中,併為 maintenance.<task>.schedule 啟用一些推薦的配置值。啟用的任務可以安全地在後臺執行,而不會干擾前臺程序。

如果 maintenance.strategy 配置值未事先設定,register 子命令還會將其設定為 incrementalincremental 策略為每個維護任務使用以下計劃:

  • gc: 停用。

  • commit-graph: 每小時。

  • prefetch: 每小時。

  • loose-objects: 每天。

  • incremental-repack: 每天。

git maintenance register 還將透過在當前倉庫中設定 maintenance.auto = false 來停用前臺維護。此配置設定在 git maintenance unregister 命令之後仍將保留。

unregister

從後臺維護中移除當前倉庫。這僅將倉庫從配置列表中移除。它不會停止後臺維護程序的執行。

如果當前倉庫尚未註冊,unregister 子命令將報告錯誤。即使當前倉庫未註冊,也可以使用 --force 選項返回成功。

任務

commit-graph

commit-graph 任務會增量更新 commit-graph 檔案,然後驗證寫入的資料是否正確。增量寫入可以安全地與併發 Git 程序一起執行,因為它不會使之前 commit-graph-chain 檔案中的 .graph 檔案過期。它們將根據過期延遲在稍後執行時被刪除。

prefetch

prefetch 任務使用所有註冊遠端倉庫的最新物件更新物件目錄。對於每個遠端倉庫,都會執行 git fetch 命令。配置的 refspec 會被修改,以便將所有請求的引用放置在 refs/prefetch/ 中。此外,標籤不會被更新。

這樣做是為了避免中斷遠端跟蹤分支。終端使用者希望這些引用保持不變,除非他們發起獲取操作。但是,透過預取任務,完成後續實際獲取所需的物件將已被獲取,從而使實際獲取更快。在理想情況下,它將僅僅是更新一組遠端跟蹤分支,而無需任何物件傳輸。

remote.<name>.skipFetchAll 配置可用於將特定遠端倉庫排除在預取之外。

gc

清理不必要的檔案並最佳化本地倉庫。“GC”代表“垃圾回收”,但此任務執行許多較小的任務。對於大型倉庫而言,此任務可能開銷較大,因為它會將所有 Git 物件重新打包到一個 pack 檔案中。在某些情況下,它也可能具有破壞性,因為它會刪除陳舊資料。有關 Git 中垃圾回收的更多詳細資訊,請參閱 git-gc[1]

loose-objects

loose-objects 任務清理鬆散物件並將其放入 pack 檔案中。為了防止與併發 Git 命令發生競爭條件,它遵循兩步過程。首先,它刪除 pack 檔案中已存在的任何鬆散物件;併發 Git 程序將檢查 pack 檔案中的物件資料,而不是鬆散物件。其次,它建立一個新的 pack 檔案(以“loose-”開頭),其中包含一批鬆散物件。

批處理大小預設為五萬個物件,以防止任務在包含許多鬆散物件的倉庫上花費太長時間。使用 maintenance.loose-objects.batchSize 配置選項調整此大小,包括值 0 以取消限制。

gc 任務將不可達物件作為鬆散物件寫入,以便僅在它們未被重新新增到 pack 檔案中時才在後續步驟中清理;因此,不建議同時啟用 loose-objectsgc 任務。

incremental-repack

incremental-repack 任務使用 multi-pack-index 功能重新打包物件目錄。為了防止與併發 Git 命令發生競爭條件,它遵循兩步過程。首先,它呼叫 git multi-pack-index expire 來刪除未被 multi-pack-index 檔案引用的 pack 檔案。其次,它呼叫 git multi-pack-index repack 來選擇幾個小的 pack 檔案並將它們重新打包成一個更大的檔案,然後更新引用小 pack 檔案的 multi-pack-index 條目以引用新的 pack 檔案。這為在下一次執行 git multi-pack-index expire 時刪除這些小 pack 檔案做準備。小 pack 檔案的選擇使得大 pack 檔案的預期大小至少是批處理大小;有關 repack 子命令的 --batch-size 選項,請參閱 git-multi-pack-index[1]。預設的批處理大小為零,這是一個特殊情況,它嘗試將所有 pack 檔案重新打包到一個 pack 檔案中。

pack-refs

pack-refs 任務收集鬆散的引用檔案並將它們收集到一個檔案中。這會加快需要遍歷許多引用的操作。有關更多資訊,請參閱 git-pack-refs[1]

reflog-expire

reflog-expire 任務刪除 reflog 中早於過期閾值的所有條目。有關更多資訊,請參閱 git-reflog[1]

rerere-gc

rerere-gc 任務呼叫垃圾回收以清理 rerere 快取中的陳舊條目。有關更多資訊,請參閱 git-rerere[1]

worktree-prune

worktree-prune 任務刪除陳舊或損壞的工作區。有關更多資訊,請參閱 git-worktree[1]

選項

--auto

run 子命令結合使用時,僅當滿足某些閾值時才執行維護任務。例如,當鬆散物件的數量超過 gc.auto 配置設定中儲存的數量時,或者當 pack 檔案數量超過 gc.autoPackLimit 配置設定時,gc 任務會執行。與 --schedule 選項不相容。

--schedule

run 子命令結合使用時,僅當滿足某些時間條件時才執行維護任務,具體由每個 <task>maintenance.<task>.schedule 配置值指定。此配置值指定自該任務上次執行以來(根據 maintenance.<task>.lastRun 配置值)的秒數。被測試的任務是那些由 --task=<task> 選項提供的任務,或者那些 maintenance.<task>.enabled 設定為 true 的任務。

--quiet

不透過 stderr 報告進度或其他資訊。

--task=<task>

如果指定此選項一次或多次,則僅按指定順序執行指定任務。如果未指定 --task=<task> 引數,則僅考慮將 maintenance.<task>.enabled 配置為 true 的任務。有關接受的 <task> 值列表,請參閱任務部分。

--scheduler=auto|crontab|systemd-timer|launchctl|schtasks

start 子命令結合使用時,指定用於執行 git maintenance run 的每小時、每天和每週執行的排程程式。<scheduler> 的可能值為 autocrontab (POSIX)、systemd-timer (Linux)、launchctl (macOS) 和 schtasks (Windows)。當指定 auto 時,將使用適當的平臺特定排程程式;在 Linux 上,如果可用則使用 systemd-timer,否則使用 crontab。預設為 auto

故障排除

git maintenance 命令旨在簡化倉庫維護模式,同時最大限度地減少 Git 命令期間的使用者等待時間。提供了各種配置選項,允許自定義此過程。預設維護選項側重於即使在大型倉庫上也能快速完成的操作。

使用者可能會發現某些情況下,計劃的維護任務沒有按預期頻繁執行。每個 git maintenance run 命令都會鎖定倉庫的物件資料庫,這會阻止其他併發的 git maintenance run 命令在同一倉庫上執行。如果沒有這種保護措施,相互競爭的程序可能會使倉庫處於不可預測的狀態。

後臺維護計劃每小時執行 git maintenance run 程序。每次執行都會執行“每小時”任務。在午夜,該程序還會執行“每日”任務。在每週的第一天的午夜,該程序還會執行“每週”任務。一個單獨的程序會遍歷每個已註冊的倉庫,執行該頻率下計劃的任務。這些程序針對每個客戶端安排在小時的隨機分鐘執行,以分散多個客戶端可能產生的負載(例如來自預取)。根據註冊倉庫的數量和大小,此過程可能需要一個多小時。在這種情況下,多個 git maintenance run 命令可能同時在同一倉庫上執行,在物件資料庫鎖上發生衝突。這導致其中一個任務無法執行。

如果您發現某些維護視窗需要一個多小時才能完成,那麼請考慮降低維護任務的複雜性。例如,gc 任務比 incremental-repack 任務慢得多。然而,這會以略大的物件資料庫為代價。考慮將開銷更大的任務安排為不那麼頻繁地執行。

專家使用者可以考慮使用與透過 git maintenance start 和 Git 配置選項提供的計劃不同的計劃來安排自己的維護任務。這些使用者應該瞭解物件資料庫鎖以及併發 git maintenance run 命令的行為方式。此外,git gc 命令不應與 git maintenance run 命令結合使用。git gc 修改物件資料庫,但不會像 git maintenance run 那樣獲取鎖。如果可能,請使用 git maintenance run --task=gc 而不是 git gc

以下部分描述了透過 git maintenance start 執行後臺維護的機制以及如何自定義它們。

POSIX 系統上的後臺維護

在 POSIX 系統上排程後臺任務的標準機制是 cron(8)。此工具根據給定的計劃執行命令。透過執行 crontab -l 可以找到當前使用者計劃任務列表。git maintenance start 寫入的計劃類似於這樣

# BEGIN GIT MAINTENANCE SCHEDULE
# The following schedule was created by Git
# Any edits made in this region might be
# replaced in the future by a Git command.

0 1-23 * * * "/<path>/git" --exec-path="/<path>" for-each-repo --config=maintenance.repo maintenance run --schedule=hourly
0 0 * * 1-6 "/<path>/git" --exec-path="/<path>" for-each-repo --config=maintenance.repo maintenance run --schedule=daily
0 0 * * 0 "/<path>/git" --exec-path="/<path>" for-each-repo --config=maintenance.repo maintenance run --schedule=weekly

# END GIT MAINTENANCE SCHEDULE

註釋用作標記 Git 寫入的計劃的區域。此區域內的任何修改都將被 git maintenance stop 完全刪除或被 git maintenance start 覆蓋。

crontab 條目指定 git 可執行檔案的完整路徑,以確保執行的 git 命令與發出 git maintenance start 時使用的命令相同,而不受 PATH 的影響。如果同一使用者使用多個 Git 可執行檔案執行 git maintenance start,則僅使用最新的可執行檔案。

這些命令使用 git for-each-repo --config=maintenance.repomaintenance.repo 多值配置選項中列出的每個倉庫上執行 git maintenance run --schedule=<frequency>。這些通常從使用者特定的全域性配置中載入。git maintenance 程序然後使用 maintenance.<task>.schedule 配置選項,確定每個 <frequency> 下配置為在每個倉庫上執行的維護任務。這些值從全域性或倉庫配置值中載入。

如果配置值不足以實現您所需的後臺維護計劃,那麼您可以建立自己的計劃。如果您執行 crontab -e,則編輯器將載入您使用者特定的 cron 計劃。在該編輯器中,您可以新增自己的計劃行。您可以從調整前面列出的預設計劃開始,或者閱讀 crontab(5) 文件以瞭解高階排程技術。請務必使用預設計劃中的完整路徑和 --exec-path 技術,以確保您在計劃中執行正確的二進位制檔案。

Linux Systemd 系統上的後臺維護

雖然 Linux 支援 cron,但根據發行版的不同,cron 可能是一個可選包,不一定安裝。在現代 Linux 發行版上,systemd 定時器正在取代它。

如果使用者 systemd 定時器可用,它們將作為 cron 的替代品。

在這種情況下,git maintenance start 將建立使用者 systemd 定時器單元並啟動定時器。透過執行 systemctl --user list-timers 可以找到當前使用者計劃任務列表。git maintenance start 寫入的定時器類似於這樣

$ systemctl --user list-timers
NEXT                         LEFT          LAST                         PASSED     UNIT                         ACTIVATES
Thu 2021-04-29 19:00:00 CEST 42min left    Thu 2021-04-29 18:00:11 CEST 17min ago  git-maintenance@hourly.timer git-maintenance@hourly.service
Fri 2021-04-30 00:00:00 CEST 5h 42min left Thu 2021-04-29 00:00:11 CEST 18h ago    git-maintenance@daily.timer  git-maintenance@daily.service
Mon 2021-05-03 00:00:00 CEST 3 days left   Mon 2021-04-26 00:00:11 CEST 3 days ago git-maintenance@weekly.timer git-maintenance@weekly.service

每個 --schedule=<frequency> 選項都會註冊一個定時器。

systemd 單元的定義可以在以下檔案中檢視

~/.config/systemd/user/git-maintenance@.timer
~/.config/systemd/user/git-maintenance@.service
~/.config/systemd/user/timers.target.wants/git-maintenance@hourly.timer
~/.config/systemd/user/timers.target.wants/git-maintenance@daily.timer
~/.config/systemd/user/timers.target.wants/git-maintenance@weekly.timer

git maintenance start 將覆蓋這些檔案並再次使用 systemctl --user 啟動定時器,因此任何自定義都應透過建立放置檔案(即 ~/.config/systemd/user/git-maintenance@.service.d 目錄中以 .conf 結尾的檔案)來完成。

git maintenance stop 將停止使用者 systemd 定時器並刪除上述檔案。

有關更多詳細資訊,請參閱 systemd.timer(5)

macOS 系統上的後臺維護

雖然 macOS 技術上支援 cron,但使用 crontab -e 需要提升的許可權,並且執行的程序沒有完整的使用者上下文。如果沒有完整的使用者上下文,Git 及其憑證助手將無法訪問儲存的憑證,因此某些維護任務將無法執行。

相反,git maintenance startlaunchctl 工具互動,這是在 macOS 中安排定時任務的推薦方式。透過 git maintenance (start|stop) 安排維護需要一些僅在 macOS 10.11 或更高版本中可用的 launchctl 功能。

您的使用者特定計劃任務以 XML 格式的 .plist 檔案儲存在 ~/Library/LaunchAgents/ 中。您可以使用以下命令檢視當前註冊的任務

$ ls ~/Library/LaunchAgents/org.git-scm.git*
org.git-scm.git.daily.plist
org.git-scm.git.hourly.plist
org.git-scm.git.weekly.plist

每個 --schedule=<frequency> 選項都會註冊一個任務。要檢視 XML 格式如何描述每個計劃,請在編輯器中開啟其中一個 .plist 檔案,並檢查 <key>StartCalendarInterval</key> 元素後面的 <array> 元素。

git maintenance start 將覆蓋這些檔案並再次使用 launchctl 註冊任務,因此任何自定義都應透過建立具有不同名稱的自己的 .plist 檔案來完成。類似地,git maintenance stop 命令將使用 launchctl 登出任務並刪除 .plist 檔案。

要對後臺任務進行更高階的自定義,請參閱 launchctl.plist(5) 以獲取更多資訊。

Windows 系統上的後臺維護

Windows 不支援 cron,而是有自己的後臺任務排程系統。git maintenance start 命令使用 schtasks 命令向該系統提交任務。您可以使用任務計劃程式應用程式檢查所有後臺任務。Git 新增的任務名稱形式為 Git Maintenance (<frequency>)。任務計劃程式 GUI 有檢查這些任務的方法,但您也可以將任務匯出到 XML 檔案並在其中檢視詳細資訊。

請注意,由於 Git 是一個控制檯應用程式,這些後臺任務會建立一個對當前使用者可見的控制檯視窗。這可以透過在任務計劃程式中選擇“無論使用者是否登入都執行”選項手動更改。此更改需要輸入密碼,這就是 git maintenance start 預設不選擇它的原因。

如果您想自定義後臺任務,請重新命名任務,以便將來呼叫 git maintenance (start|stop) 時不會覆蓋您的自定義任務。

配置

本節中以下所有內容均從 git-config[1] 文件中選擇性地包含。內容與彼處相同:

maintenance.auto

此布林配置選項控制某些命令在完成其正常工作後是否執行 git maintenance run --auto。預設為 true。

maintenance.autoDetach

許多 Git 命令在將資料寫入倉庫後會觸發自動維護。此布林配置選項控制此自動維護是應在前臺進行,還是維護程序應分離並在後臺繼續執行。

如果未設定,則使用 gc.autoDetach 的值作為備用。如果兩者都未設定,則預設為 true,這意味著維護程序將分離。

maintenance.strategy

此字串配置選項提供了一種指定後臺維護的幾種推薦計劃之一的方法。這僅影響在 git maintenance run --schedule=X 命令期間執行哪些任務,前提是沒有提供 --task=<task> 引數。此外,如果設定了 maintenance.<task>.schedule 配置值,則使用該值而不是 maintenance.strategy 提供的值。可能的策略字串包括

  • none: 此預設設定意味著在任何計劃下都不執行任務。

  • incremental: 此設定優化了執行不刪除任何資料的小型維護活動。它不安排 gc 任務,但每小時執行 prefetchcommit-graph 任務,每天執行 loose-objectsincremental-repack 任務,每週執行 pack-refs 任務。

maintenance.<task>.enabled

此布林配置選項控制當未向 git maintenance run 指定 --task 選項時,是否執行名稱為 <task> 的維護任務。如果存在 --task 選項,則這些配置值將被忽略。預設情況下,只有 maintenance.gc.enabled 為 true。

maintenance.<task>.schedule

此配置選項控制給定的 <task> 是否在 git maintenance run --schedule=<frequency> 命令期間執行。該值必須是“hourly”、“daily”或“weekly”之一。

maintenance.commit-graph.auto

此整數配置選項控制 commit-graph 任務作為 git maintenance run --auto 的一部分應該執行的頻率。如果為零,則 commit-graph 任務將不會與 --auto 選項一起執行。負值將強制任務每次都執行。否則,正值意味著當不在 commit-graph 檔案中的可達提交數量至少為 maintenance.commit-graph.auto 的值時,命令應執行。預設值為 100。

maintenance.loose-objects.auto

此整數配置選項控制 loose-objects 任務作為 git maintenance run --auto 的一部分應該執行的頻率。如果為零,則 loose-objects 任務將不會與 --auto 選項一起執行。負值將強制任務每次都執行。否則,正值意味著當鬆散物件的數量至少為 maintenance.loose-objects.auto 的值時,命令應執行。預設值為 100。

maintenance.loose-objects.batchSize

此整數配置選項控制在 loose-objects 任務期間寫入 pack 檔案中的鬆散物件的最大數量。預設值為五萬。使用值 0 表示沒有限制。

maintenance.incremental-repack.auto

此整數配置選項控制 incremental-repack 任務作為 git maintenance run --auto 的一部分應該執行的頻率。如果為零,則 incremental-repack 任務將不會與 --auto 選項一起執行。負值將強制任務每次都執行。否則,正值意味著當不在多 pack 索引中的 pack 檔案數量至少為 maintenance.incremental-repack.auto 的值時,命令應執行。預設值為 10。

maintenance.reflog-expire.auto

此整數配置選項控制 reflog-expire 任務作為 git maintenance run --auto 的一部分應該執行的頻率。如果為零,則 reflog-expire 任務將不會與 --auto 選項一起執行。負值將強制任務每次都執行。否則,正值意味著當“HEAD”reflog 中過期的 reflog 條目數量至少為 maintenance.loose-objects.auto 的值時,命令應執行。預設值為 100。

maintenance.rerere-gc.auto

此整數配置選項控制 rerere-gc 任務作為 git maintenance run --auto 的一部分應該執行的頻率。如果為零,則 rerere-gc 任務將不會與 --auto 選項一起執行。負值將強制任務每次都執行。否則,任何正值都意味著當“rr-cache”目錄存在且至少包含一個條目時(無論其是否陳舊)命令都將執行。此啟發式方法可能會在將來進行改進。預設值為 1。

maintenance.worktree-prune.auto

此整數配置選項控制 worktree-prune 任務作為 git maintenance run --auto 的一部分應該執行的頻率。如果為零,則 worktree-prune 任務將不會與 --auto 選項一起執行。負值將強制任務每次都執行。否則,正值意味著當可修剪的工作區數量超過該值時,命令應執行。預設值為 1。

GIT

Git[1] 套件的一部分

scroll-to-top