Git
英文 ▾ 主題 ▾ 最新版本 ▾ git-pack-objects 最後更新於 2.43.0

名稱

git-pack-objects - 建立物件的壓縮封存

概要

git pack-objects [-q | --progress | --all-progress] [--all-progress-implied]
	[--no-reuse-delta] [--delta-base-offset] [--non-empty]
	[--local] [--incremental] [--window=<n>] [--depth=<n>]
	[--revs [--unpacked | --all]] [--keep-pack=<pack-name>]
	[--cruft] [--cruft-expiration=<time>]
	[--stdout [--filter=<filter-spec>] | <base-name>]
	[--shallow] [--keep-true-parents] [--[no-]sparse] < <object-list>

描述

從標準輸入讀取物件清單,並將一個或多個具有指定基本名稱的壓縮封存寫入磁碟,或將壓縮封存寫入標準輸出。

壓縮封存是在兩個儲存庫之間傳輸一組物件的有效方式,也是一種存取效率高的封存格式。在壓縮封存中,物件可以壓縮完整儲存,也可以與其他物件的差異形式儲存。後者通常稱為增量。

壓縮封存格式 (.pack) 設計為自包含,因此可以在沒有任何其他資訊的情況下解壓縮。因此,增量所依賴的每個物件都必須存在於封存中。

會產生一個封存索引檔案 (.idx),以便快速隨機存取封存中的物件。將索引檔案 (.idx) 和壓縮封存 (.pack) 都放置在 $GIT_OBJECT_DIRECTORY 的 pack/ 子目錄(或 $GIT_ALTERNATE_OBJECT_DIRECTORIES 中的任何目錄)中,可以讓 Git 從壓縮封存讀取。

git unpack-objects 命令可以讀取壓縮封存,並將封存中包含的物件展開為「單檔案單物件」格式;當同儕為了高效網路傳輸而動態建立封存時,通常由智慧提取命令執行此操作。

選項

base-name

使用 <base-name> 來決定建立的檔案名稱,寫入成對的檔案 (.pack 和 .idx)。當使用此選項時,成對的兩個檔案會寫入 <base-name>-<SHA-1>.{pack,idx} 檔案中。 <SHA-1> 是基於封存內容的雜湊值,並會寫入命令的標準輸出。

--stdout

將封存內容(原本會寫入 .pack 檔案的內容)寫出至標準輸出。

--revs

從標準輸入讀取修訂引數,而不是個別的物件名稱。修訂引數的處理方式與 git rev-list--objects 旗標使用其 commit 引數來建立其輸出的物件清單的方式相同。產生的清單上的物件會被壓縮。除了修訂之外,也會接受 --not--shallow <SHA-1> 行。

--unpacked

這表示 --revs。在處理從標準輸入讀取的修訂引數清單時,將壓縮的物件限制為尚未壓縮的物件。

--all

這表示 --revs。除了從標準輸入讀取的修訂引數清單之外,假設指定包含 refs/ 下的所有參考。

--include-tag

如果所參考的物件已包含在產生的封存檔中,則包含未要求的附註標籤。這對於將新標籤傳送至原生 Git 用戶端很有用。

--stdin-packs

從標準輸入讀取封存檔的基本名稱 (例如,pack-1234abcd.pack),而不是物件名稱或修訂引數。產生的封存包含所包含封存中列出的所有物件(那些不是以 ^ 開頭的),但不包含排除封存中列出的任何物件(以 ^ 開頭的)。

--revs 或表示 --revs 的選項(例如 --all)不相容,但 --unpacked 除外,後者是相容的。

--cruft

將無法存取的物件壓縮到單獨的「垃圾」封存中,該封存由 .mtimes 檔案的存在表示。通常由 git repack --cruft 使用。呼叫者提供封存名稱清單,並指示哪些封存將保留在儲存庫中,以及哪些封存將被刪除(以 - 字首表示)。垃圾封存的內容是不在倖存封存中且未超過寬限期的所有物件(請參閱下方的 --cruft-expiration),或已超過寬限期,但可從另一個尚未超過寬限期的物件存取的所有物件。

當輸入列出包含所有可存取物件的封存(並將所有其他封存列為待刪除)時,對應的垃圾封存將包含所有無法存取的物件(mtime 新於 --cruft-expiration),以及任何無法存取且 mtime 早於 --cruft-expiration,但可從 mtime 新於 --cruft-expiration 的無法存取物件存取的物件。

--unpack-unreachable--keep-unreachable--pack-loose-unreachable--stdin-packs,以及任何其他表示 --revs 的選項不相容。

--cruft-expiration=<approxidate>

如果指定,如果物件的 mtime 早於 <approxidate>,則會將其從垃圾封存中移除。如果未指定(並給定 --cruft),則不會移除任何物件。

--window=<n>
--depth=<n>

這兩個選項會影響如何使用增量壓縮來儲存封存中包含的物件。物件首先會在內部依類型、大小和選擇性名稱排序,並與 --window 中的其他物件進行比較,以判斷使用增量壓縮是否能節省空間。--depth 會限制最大增量深度;太深會影響解壓縮器的效能,因為需要多次套用增量資料才能取得必要的物件。

--window 的預設值為 10,而 --depth 的預設值為 50。最大深度為 4095。

--window-memory=<n>

此選項在 --window 的基礎上提供額外的限制;視窗大小會動態縮減,以確保記憶體使用量不會超過 <n> 位元組。這在具有大小物件混合的儲存庫中很有用,可以在大型視窗的情況下不耗盡記憶體,但仍然能夠利用小型物件的大型視窗。大小可以附加 "k"、"m" 或 "g"。--window-memory=0 會讓記憶體使用量不受限制。預設值取自 pack.windowMemory 設定變數。

--max-pack-size=<n>

在不尋常的情況下,您可能無法在您的檔案系統上建立大於特定大小的檔案,並且可以使用此選項來告知命令將輸出封存檔分割為多個獨立的封存檔,每個封存檔的大小都不超過指定的大小。大小可以附加 "k"、"m" 或 "g"。允許的最小大小限制為 1 MiB。除非設定設定變數 pack.packSizeLimit,否則預設為無限制。請注意,此選項可能會導致儲存庫更大且速度更慢;請參閱 pack.packSizeLimit 中的討論。

--honor-pack-keep

此旗標會導致忽略本機封存中已經具有 .keep 檔案的物件,即使該物件本應被壓縮。

--keep-pack=<pack-name>

此旗標會導致忽略給定封存中已經存在的物件,即使該物件本應被壓縮。<pack-name> 是封存檔案名稱,不帶前導目錄 (例如,pack-123.pack)。可以多次指定此選項以保留多個封存。

--incremental

此旗標會導致忽略封存中已經存在的物件,即使該物件本應被壓縮。

--local

此旗標會導致忽略從替代物件儲存借用的物件,即使該物件本應被壓縮。

--non-empty

只有在壓縮封存至少包含一個物件時才建立。

--progress

預設情況下,當標準錯誤流連接到終端機時,會回報進度狀態,除非指定 -q。此旗標會強制回報進度狀態,即使標準錯誤流未導向終端機。

--all-progress

當指定 --stdout 時,會在物件計數和壓縮階段顯示進度報告,但在寫出階段則會抑制。原因是,在某些情況下,輸出串流會直接連結到另一個可能希望在處理輸入的封包資料時顯示自身進度狀態的命令。這個旗標類似於 --progress,但即使使用了 --stdout,它也會強制在寫出階段顯示進度報告。

--all-progress-implied

此選項用於在啟用進度顯示時,隱含地使用 --all-progress。與 --all-progress 不同,此旗標本身不會強制顯示任何進度。

-q

此旗標會使命令不在標準錯誤串流上報告其進度。

--no-reuse-delta

當在具有現有封包的儲存庫中建立封裝的歸檔檔時,此命令會重複使用現有的差異。這有時會導致稍微次優的封包。此旗標會告知命令不要重複使用現有的差異,而是從頭開始計算它們。

--no-reuse-object

此旗標會告知命令完全不要重複使用現有的物件資料,包括非差異化的物件,強制重新壓縮所有內容。這表示使用 --no-reuse-delta。僅在希望對封裝資料強制執行不同壓縮級別的模糊情況下才有用。

--compression=<n>

指定在產生的封包中新壓縮資料的壓縮級別。如果未指定,則封包壓縮級別會先由 pack.compression 決定,然後由 core.compression 決定,如果兩者都未設定,則預設為 -1,即 zlib 的預設值。如果您想強制對所有資料都使用一致的壓縮級別,無論來源為何,請新增 --no-reuse-object。

--[no-]sparse

當與 "--revs" 選項結合使用時,切換「稀疏」演算法以決定要將哪些物件包含在封包中。此演算法只會遍歷在引入新物件的路徑中出現的樹狀結構。當計算要傳送小變更的封包時,這可以顯著提高效能。但是,如果包含的提交包含某些類型的直接重新命名,則可能會將額外的物件新增到封包檔案中。如果未包含此選項,則預設為 pack.useSparse 的值,除非另有指定,否則為 true。

--thin

透過省略傳送者和接收者之間的共同物件來建立「精簡」封包,以減少網路傳輸。此選項僅在與 --stdout 結合使用時才有意義。

注意:精簡封包會省略必要的物件,因而違反了封裝的歸檔格式,因此 Git 無法使用,除非使其自行包含。使用 git index-pack --fix-thin (請參閱 git-index-pack[1]) 來還原自行包含的屬性。

--shallow

最佳化將提供給具有淺層儲存庫之用戶端的封包。此選項與 --thin 結合使用,可能會以速度為代價產生較小的封包。

--delta-base-offset

封裝的歸檔檔可以將差異的基礎物件表示為 20 位元組的物件名稱或串流中的位移,但舊版的 Git 不理解後者。預設情況下,git pack-objects 僅使用前一種格式以獲得更好的相容性。此選項允許命令使用後一種格式以提高緊湊性。根據平均差異鏈長度,此選項通常會將產生的封包檔案縮小 3-5%。

注意:當瓷器命令 (例如 git gc (請參閱 git-gc[1])、git repack (請參閱 git-repack[1])) 在將儲存庫中的物件放入封包檔案時,會在現代 Git 中預設傳遞此選項。git bundle (請參閱 git-bundle[1]) 在建立套件時也是如此。

--threads=<n>

指定在搜尋最佳差異比對時要產生的執行緒數目。這需要使用 pthreads 編譯 pack-objects,否則會忽略此選項並顯示警告。這旨在減少多處理器電腦上的封裝時間。但是,差異搜尋視窗所需的記憶體量會乘以執行緒數目。指定 0 會讓 Git 自動偵測 CPU 的數量,並據此設定執行緒數目。

--index-version=<version>[,<offset>]

這僅供測試套件使用。它允許強制指定產生的封包索引的版本,並在位於給定位移之上的物件上強制使用 64 位元索引項目。

--keep-true-parents

使用此選項,即使父項被移植隱藏,也會將其封裝。

--filter=<filter-spec>

從產生的封包檔案中省略某些物件 (通常是 Blob)。請參閱 git-rev-list[1] 以了解有效的 <filter-spec> 格式。

--no-filter

關閉任何先前的 --filter= 引數。

--missing=<missing-action>

一個偵錯選項,用於協助未來「部分複製」的開發。此選項指定如何處理遺失的物件。

--missing=error 形式會要求 pack-objects 在遇到遺失的物件時停止並顯示錯誤。如果儲存庫是部分複製,則會在宣告其遺失之前嘗試提取遺失的物件。這是預設動作。

--missing=allow-any 形式允許在遇到遺失的物件時繼續物件遍歷。不會發生遺失物件的提取。遺失的物件會靜默地從結果中省略。

--missing=allow-promisor 形式類似於 allow-any,但只允許對預期的 promisor 遺失物件繼續物件遍歷。不會發生遺失物件的提取。意外的遺失物件會引發錯誤。

--exclude-promisor-objects

省略已知在 promisor 遠端中的物件。(此選項的目的是僅對本機建立的物件進行操作,以便在我們重新封裝時,我們仍然可以區分本機建立的物件 [不含 .promisor] 和來自 promisor 遠端的物件 [含 .promisor]。) 此選項用於部分複製。

--keep-unreachable

除了未標記為 *.keep 檔案之封包中的可存取物件外,還會將使用 --unpacked= 選項命名的封包中無法從 ref 存取的物件新增至產生的封包。這表示使用 --revs

--pack-loose-unreachable

封裝無法存取的鬆散物件 (並移除其鬆散的對應項)。這表示使用 --revs

--unpack-unreachable

以鬆散形式保留無法存取的物件。這表示使用 --revs

--delta-islands

根據「島嶼」限制差異比對。請參閱下方的「差異島嶼」。

差異島嶼

在可能的情況下,pack-objects 會嘗試重複使用現有的磁碟差異,以避免需要動態搜尋新的差異。這是用於服務提取的重要最佳化,因為這表示伺服器可以完全避免膨脹大多數物件,而只需直接從磁碟傳送位元組。當物件以差異形式儲存,且該差異的基礎是接收者沒有 (且我們尚未傳送) 的物件時,此最佳化無法運作。在這種情況下,伺服器會「中斷」差異,且必須尋找新的差異,這會產生很高的 CPU 成本。因此,為了提高效能,磁碟上差異關係中的物件集必須與用戶端將提取的物件集相符。

在正常的儲存庫中,這往往會自動運作。物件大多可從分支和標籤存取,這也是用戶端提取的內容。我們在伺服器上找到的任何差異都可能存在於用戶端具有或將具有的物件之間。

但是在某些儲存庫設定中,您可能有多個相關但獨立的 ref 提示群組,而用戶端傾向於獨立提取這些群組。例如,假設您在單一共享物件存放區中託管多個儲存庫「分支」,並允許用戶端透過 GIT_NAMESPACE 或使用替代機制的個別儲存庫將它們視為個別儲存庫。單純的重新封裝可能會發現,物件的最佳差異是針對僅在另一個分支中找到的基礎。但是,當用戶端提取時,他們不會有基礎物件,而且我們必須動態尋找新的差異。

如果您在 refs/heads/refs/tags/ 之外有多個指向相關物件的 ref (例如,某些託管提供者使用的 refs/pullrefs/changes),則可能會出現類似情況。預設情況下,用戶端只提取 HEAD 和標籤,且針對僅在那些其他群組中找到的物件的差異無法按原樣傳送。

差異島嶼透過允許您將 ref 分組到不同的「島嶼」來解決此問題。Pack-objects 會計算哪些物件可從哪些島嶼存取,並拒絕從物件 A 建立針對未出現在 A 的所有島嶼中的基礎的差異。這會導致封包稍微變大 (因為我們錯失了一些差異機會),但保證提取一個島嶼不會因為跨越島嶼邊界而必須動態重新計算差異。

使用差異島嶼重新封裝時,差異視窗往往會因設定禁止的候選物件而阻塞。使用較大的 --window 重新封裝有幫助 (而且不會像原本可能的那樣花費太多時間,因為我們可以在對內容執行任何計算之前,根據島嶼拒絕某些物件配對)。

島嶼是透過 pack.island 選項設定的,可以多次指定。每個值都是一個以左錨定方式與 refname 匹配的正規表示式。例如

[pack]
island = refs/heads/
island = refs/tags/

將 HEAD 和標籤放入一個島嶼 (其名稱為空字串;請參閱下方有關命名的詳細資訊)。任何與這些正規表示式不匹配的 ref (例如 refs/pull/123) 都不在任何島嶼中。因此,僅可從 refs/pull/ (但不是 HEAD 或標籤) 存取的任何物件都不是用作 refs/heads/ 的基礎的候選物件。

Refs 會根據其「名稱」分組到不同的島嶼中,而兩個產生相同名稱的正規表達式會被視為在同一個島嶼中。名稱是從正規表達式計算出來的,方法是將正規表達式中所有的捕捉群組串連起來,並在之間加上一個 - 破折號。(如果沒有捕捉群組,則名稱為空字串,如以上範例所示。) 這讓您可以建立任意數量的島嶼。但是,僅支援最多 14 個此類捕捉群組。

例如,想像一下您將每個分支的 refs 儲存在 refs/virtual/ID 中,其中 ID 是一個數字識別碼。您可能會設定

[pack]
island = refs/virtual/([0-9]+)/heads/
island = refs/virtual/([0-9]+)/tags/
island = refs/virtual/([0-9]+)/(pull)/

這樣會將每個分支的 head 和 tag 放入它們自己的島嶼中(名稱為 "1234" 或類似的名稱),而每個的 pull refs 則會進入它們自己的 "1234-pull" 島嶼。

請注意,我們為每個正規表達式選擇一個單獨的島嶼,使用「最後一個勝出」的排序方式 (這允許 repo 特定設定優先於使用者範圍設定,依此類推)。

組態設定

各種組態變數會影響封裝,請參閱 git-config[1](搜尋 "pack" 和 "delta")。

值得注意的是,delta 壓縮不會用於大於 core.bigFileThreshold 組態變數的物件以及具有 delta 屬性設定為 false 的檔案。

GIT

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

scroll-to-top