Git
英文 ▾ 主題 ▾ 最新版本 ▾ git-maintenance 最後更新於 2.47.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 配置值。啟用的任務適合在背景執行,而不會干擾前景程序。

如果先前未設定,則 register 子命令也會將 maintenance.strategy 配置值設定為 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 放置在 refs/prefetch/ 中。此外,不會更新標籤。

這樣做是為了避免干擾遠端追蹤分支。終端使用者希望這些 refs 保持不動,除非他們啟動提取。但是,使用 prefetch 任務,完成稍後實際提取所需的物件將已取得,從而使實際提取更快。在理想情況下,它只會成為一堆遠端追蹤分支的更新,而不會進行任何物件傳輸。

remote.<name>.skipFetchAll 配置可用於排除從預先提取中排除特定遠端。

gc

清理不必要的文件並最佳化本機儲存庫。「GC」代表「垃圾收集」,但此任務會執行許多較小的任務。此任務對於大型儲存庫來說可能很耗費資源,因為它會將所有 Git 物件重新打包到單一封裝檔中。在某些情況下,它也可能會造成干擾,因為它會刪除過時的資料。如需 Git 中垃圾收集的詳細資訊,請參閱git-gc[1]

loose-objects

loose-objects 工作會清理鬆散物件,並將它們放置到封裝檔中。為了防止與並行 Git 命令發生競爭狀況,它會遵循兩個步驟的程序。首先,它會刪除已存在於封裝檔中的任何鬆散物件;並行 Git 程序會檢查封裝檔以取得物件資料,而不是鬆散物件。其次,它會建立一個新的封裝檔(以 "loose-" 開頭),其中包含一批鬆散物件。批次大小限制為 5 萬個物件,以防止工作在具有許多鬆散物件的儲存庫上花費太長時間。只有當無法將無法存取的物件重新新增至封裝檔時,gc 任務才會將它們寫入為鬆散物件,以便稍後的步驟清理它們;因此,不建議同時啟用 loose-objectsgc 任務。

incremental-repack

incremental-repack 工作使用 multi-pack-index 功能重新打包物件目錄。為了防止與並行 Git 命令發生競爭狀況,它會遵循兩個步驟的程序。首先,它會呼叫 git multi-pack-index expire 以刪除 multi-pack-index 檔案未參考的封裝檔。其次,它會呼叫 git multi-pack-index repack 以選取幾個較小的封裝檔,並將它們重新打包成一個較大的封裝檔,然後更新參考較小封裝檔的 multi-pack-index 項目以參考新的封裝檔。這會在下次執行 git multi-pack-index expire 時,準備刪除這些較小的封裝檔。選取較小的封裝檔的方式是,大型封裝檔的預期大小至少為批次大小;請參閱git-multi-pack-index[1] 中的 repack 子命令的 --batch-size 選項。預設批次大小為零,這是一種特殊情況,會嘗試將所有封裝檔重新打包成單一封裝檔。

pack-refs

pack-refs 任務會收集鬆散的參考檔案,並將它們收集到單一檔案中。這會加速需要反覆運算許多參考的操作。如需詳細資訊,請參閱git-pack-refs[1]

選項

--auto

run 子命令組合使用時,只有在滿足特定閾值時才執行維護任務。例如,當鬆散物件的數量超過 gc.auto 配置設定中儲存的數量,或當封裝檔的數量超過 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 程序。每次執行都會執行「hourly」(每小時)任務。在午夜,該程序也會執行「daily」(每日)任務。在一週的第一天午夜,該程序也會執行「weekly」(每週)任務。單一程序會遍歷每個已註冊的儲存庫,針對該頻率執行排定的任務。根據已註冊的儲存庫數量及其大小,此程序可能需要超過一小時的時間。在這種情況下,多個 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.repo 在多值 maintenance.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 start 會與 launchctl 工具互動,這是建議在 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

此字串設定選項提供一種方式,可指定幾個建議的背景維護排程之一。這只會影響在沒有提供 --task=<task> 引數的情況下,git maintenance run --schedule=X 命令期間會執行哪些任務。此外,如果設定了 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 檔案中的可達 commit 數量至少為 maintenance.commit-graph.auto 的值時,該命令才應執行。預設值為 100。

maintenance.loose-objects.auto

此整數設定選項控制 loose-objects 工作在 git maintenance run --auto 中應執行的頻率。若為零,則 loose-objects 工作不會透過 --auto 選項執行。負值會強制每次都執行該工作。否則,正值表示當鬆散物件的數量至少為 maintenance.loose-objects.auto 的值時,該命令才應執行。預設值為 100。

maintenance.incremental-repack.auto

此整數設定選項控制 incremental-repack 工作在 git maintenance run --auto 中應執行的頻率。若為零,則 incremental-repack 工作不會透過 --auto 選項執行。負值會強制每次都執行該工作。否則,正值表示當不在多重索引包中的 pack 檔案數量至少為 maintenance.incremental-repack.auto 的值時,該命令才應執行。預設值為 10。

GIT

git[1] 套件的一部分

scroll-to-top