Git

名稱

gitpacking - 與 Git 中的打包相關的進階概念

概要

gitpacking

描述

本文旨在描述與 Git 中打包相關的一些進階概念。

許多概念目前分散在各種 Git 命令的手冊頁面中,包括 git-pack-objects[1]git-repack[1] 和其他命令,以及 gitformat-pack[5]Documentation/technical 樹的一部分。

Git 中打包的許多方面未在本文檔中涵蓋,而是存在於上述區域。隨著時間的推移,這些分散的片段可能會合併到本文檔中。

偽合併位圖

注意
偽合併位圖被認為是一項實驗性功能,因此配置和許多想法可能會發生變化。

背景

當我們有一個或多個遍歷起點的磁碟儲存位圖時,可達性位圖最有效率。因此,Git 偏好儲存 ref 提示中 commit 的位圖,因為遍歷往往從這些點開始。

但是,如果您有大量的 ref,則為每個 ref 提示儲存位圖是不可行的。它會佔用空間,而且僅將所有這些位圖進行 OR 運算也很耗費資源。

我們可以處理這個問題的一種方法是建立代表 ref 群組的位圖。當遍歷詢問整個群組時,我們可以使用這個單一位圖,而不是單獨考慮每個 ref。由於這些位圖表示在所有 commit 的假設合併中可達到的物件集合,因此我們稱它們為偽合併位圖。

概述

「偽合併位圖」用於指一對位圖,如下所示

Commit 位圖

其設定的位描述了偽合併的「合併」位圖(如下所述)中包含的 commit 集合的位圖。

合併位圖

其設定的位描述了偽合併的「commit」位圖(如上所述)中 commit 集合的可達性閉包的位圖。對於具有與 commit 位圖中所述相同父系的章魚合併,將產生相同的位圖。

當給定偽合併的所有 commit 都列在遍歷的任一側時,偽合併位圖可以加速位圖遍歷,無論是直接(透過明確要求它們作為 HAVESWANTS 的一部分)還是間接(透過在填入遍歷期間遇到它們)。

使用案例

例如,假設存在一個具有大量 commit 的偽合併位圖,這些 commit 都列在某些位圖遍歷查詢的 WANTS 區段中。當啟用偽合併位圖時,位圖機制可以快速確定存在一個偽合併,滿足查詢任一側的部分所需物件。然後,我們可以膨脹 EWAH 壓縮的位圖,並將其 OR 運算到結果位圖中。相比之下,如果沒有偽合併位圖,我們將必須在可能大量的個別位圖上重複解壓縮和 OR 運算步驟,這可能會花費更多的時間。

當 (a) 大量的參考、(b) 位圖覆蓋率不佳,以及 (c) 深度巢狀樹時,填入遍歷相對昂貴,則會產生偽合併的另一個優點。例如,假設有大量標籤,使得單獨為每個標籤進行位圖處理是不可行的。如果沒有偽合併位圖,計算例如 git rev-list --use-bitmap-index --count --objects --tags 的結果可能需要大量的填入遍歷。但是,當大量標籤儲存在偽合併位圖中時,位圖機制可以利用我們只關心從所有這些標籤可達到的物件的聯集的事實,並更快地回答查詢。

配置

根據兩個標準將參考提示分組到不同的偽合併群組中。參考名稱符合一個或多個定義的偽合併模式,以及選擇性地符合該模式內的一個或多個捕獲群組,這些捕獲群組進一步分割群組。

在群組中,commit 可能會根據其年齡被視為「穩定」或「不穩定」。這些可以透過分別設定 bitmapPseudoMerge.<name>.stableThresholdbitmapPseudoMerge.<name>.threshold 配置值來調整。

所有穩定的 commit 都會分組到大小相等的偽合併中 (bitmapPseudoMerge.<name>.stableSize)。如果 stableSize 配置設定為 100,則前 100 個 (按提交者日期排序) 比 stableThreshold 值舊的 commit 將形成一個群組,接下來的 100 個 commit 將形成另一個群組,依此類推。

在不穩定的 commit 中,偽合併機制會嘗試將較舊的 commit 合併到大型群組中,而不是較新的 commit,這些 commit 將出現在較小的群組中。這是基於一種啟發式方法,即其提示 commit 較舊的參考,不太可能被修改為指向與其提示 commit 較新的參考不同的 commit。

群組的大小由冪律衰減函數決定,衰減參數大致對應於 f(n) = C*n^(-k/100) 中的「k」,其中 f(n) 描述第 n 個偽合併群組的大小。取樣率控制有多少百分比的符合條件的 commit 被視為候選者。閾值參數表示最小年齡(以避免在偽合併群組中包含太新的 commit,使其不太可能有效)。「maxMerges」參數設定單一群組中偽合併 commit 數量的上限

與「穩定」相關的參數控制「穩定」偽合併群組,這些群組由固定數量的 commit 組成,這些 commit 比設定的「穩定閾值」值舊,並且可以按年齡順序以「stableSize」的塊分組在一起。

偽合併的確切配置如下

注意
bitmapPseudoMerge.* 中的配置選項被視為實驗性,未來可能會發生變更或完全移除。有關偽合併位圖功能的詳細資訊,請參閱 gitpacking[7] 的「偽合併位圖」區段。
bitmapPseudoMerge.<name>.pattern

用於符合參考名稱的正規表示式。此模式符合的參考所指向的 commit(以及符合以下條件,例如 bitmapPseudoMerge.<name>.sampleRatebitmapPseudoMerge.<name>.threshold)將被視為納入偽合併位圖的候選者。

commit 會根據指向給定 commit 的任何參考是否符合模式(即擴充正規表示式)來分組到偽合併群組中。

在偽合併群組中,commit 可以根據模式中的捕獲群組進一步分組到子群組中。這些子群組是透過將正規表示式中的任何捕獲群組串聯起來,並在它們之間加上 - 短橫線來形成的。

例如,如果模式是 refs/tags/,則所有標籤(只要它們符合以下條件)都將被視為同一個偽合併群組的候選者。但是,如果模式改為 refs/remotes/([0-9])+/tags/,則來自不同遠端標籤將根據遠端號碼分組到不同的偽合併群組中。

bitmapPseudoMerge.<name>.decay

決定連續偽合併位圖群組大小縮小的速率。必須是非負數。這個參數可以被認為是函數 f(n) = C * n^-k 中的 k,其中 f(n) 是第 `n` 個群組的大小。

將衰減率設定為等於 0 會使所有群組的大小相同。將衰減率設定為等於 1 會使第 n 個群組的大小為初始群組的 1/n。衰減率的較高值會導致連續群組以越來越快的速度縮小。預設值為 1

如果所有群組的大小相同,則可能包含較新 commit 的群組的使用頻率會低於較早的群組,因為指向較新 commit 的參考比指向較舊 commit 的參考更有可能被更新。

bitmapPseudoMerge.<name>.sampleRate

決定選取以納入不穩定偽合併位圖的未位圖化的 commit(在參考提示中)的比例。必須介於 01 之間(含)。預設值為 1

bitmapPseudoMerge.<name>.threshold

決定未位圖化的 commit(在參考提示中,如上)的最小年齡,這些 commit 是納入不穩定偽合併位圖的候選者。預設值為 1.week.ago

bitmapPseudoMerge.<name>.maxMerges

決定可以分散 commit 的偽合併 commit 的最大數量。

對於其模式不包含任何捕獲群組的偽合併群組,此設定適用於所有符合正規表示式的 commit。對於具有一個或多個捕獲群組的模式,此設定適用於每個不同的捕獲群組。

舉例來說,如果您的擷取群組是 refs/tags/,那麼此設定會將所有標籤分配到最多 maxMerges 個虛擬合併提交中。但是,如果您的擷取群組是 refs/remotes/([0-9]+)/tags/,那麼此設定將會個別應用於每個遠端的一組標籤。

必須為非負數。預設值為 64。

bitmapPseudoMerge.<名稱>.stableThreshold

決定提交的最小期限(在參考提示中,如上所述,但即使穩定的提交已被位圖涵蓋,仍會被視為候選對象),這些提交是穩定虛擬合併位圖的候選對象。預設值為 1.month.ago

將此閾值設定為較小的值(例如,1.week.ago)將導致生成更多穩定的群組(會產生一次性的生成成本),但這些群組隨著時間的推移可能會過時。使用較大的值會產生相反的懲罰(較少的穩定群組,但更有用)。

bitmapPseudoMerge.<名稱>.stableSize

決定穩定虛擬合併位圖的大小(以提交次數為單位)。預設值為 512

範例

假設您有一個具有大量參考的儲存庫,並且您想要一個虛擬合併位圖的基本設定,以增強 refs/ 命名空間的位圖覆蓋率。您可以從如下所示的設定開始

[bitmapPseudoMerge "all"]
	pattern = "refs/"
	threshold = now
	stableThreshold = never
	sampleRate = 100
	maxMerges = 64

這將為所有參考建立虛擬合併位圖,無論其期限如何,並將它們分組到 64 個虛擬合併提交中。

如果您希望在生成虛擬合併提交時將標籤與分支分開,則可以改為使用擷取群組定義模式,如下所示

[bitmapPseudoMerge "all"]
	pattern = "refs/(heads/tags)/"

假設您正在一個以網路方式分叉的儲存庫中工作,每個分叉都由一些數字 ID 指定,其參考位於網路中的 refs/virtual/NNN/ 中(其中 NNN 是對應於某個分叉的數字 ID)。在這種情況下,您可以改寫成類似這樣的內容

[bitmapPseudoMerge "all"]
	pattern = "refs/virtual/([0-9]+)/(heads|tags)/"
	threshold = now
	stableThreshold = never
	sampleRate = 100
	maxMerges = 64

這將會產生類似 "1234-heads" 和 "5678-tags" 的虛擬合併群組識別符號(分別針對分叉 "1234" 中的分支和遠端 "5678" 中的標籤)。

GIT

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

scroll-to-top