簡體中文 ▾ 主題 ▾ 最新版本 ▾ git-pack-objects 最後更新於 2.52.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]
		   [--name-hash-version=<n>] [--path-walk] < <object-list>

描述

從標準輸入讀取物件列表,並將指定基礎名稱的一個或多個打包歸檔寫入磁碟,或將打包歸檔寫入標準輸出。

打包歸檔是一種在兩個倉庫之間高效傳輸一組物件的方式,也是一種訪問高效的歸檔格式。在打包歸檔中,物件要麼被儲存為壓縮的整體,要麼作為與其他物件的差異。後者通常稱為 delta。

打包歸檔格式(.pack)被設計成自包含的,以便無需額外資訊即可解包。因此,delta 所依賴的每個物件都必須存在於 pack 中。

會生成 pack 索引檔案(.idx),以實現對 pack 中物件的快速、隨機訪問。將索引檔案(.idx)和打包歸檔(.pack)都放在 $GIT_OBJECT_DIRECTORY 的 pack/ 子目錄中(或 $GIT_ALTERNATE_OBJECT_DIRECTORIES 中的任何目錄),可以使 Git 從打包歸檔中讀取。

git unpack-objects 命令可以讀取打包歸檔,並將 pack 中包含的物件擴充套件為“一個檔案一個物件”的格式;這通常由智慧拉取命令完成,當 pack 為了透過其對等方進行高效網路傳輸而即時建立時。

選項

base-name

寫入檔案對(.pack 和 .idx),使用 <base-name> 來確定建立檔案的名稱。使用此選項時,一對檔案將寫入 <base-name>-<SHA-1>.{pack,idx} 檔案。 <SHA-1> 是基於 pack 內容的雜湊,並寫入命令的標準輸出。

--stdout

將 pack 內容(將被寫入 .pack 檔案的內容)輸出到標準輸出。

--revs

從標準輸入讀取修訂引數,而不是單個物件名稱。修訂引數的處理方式與 git rev-list 使用 --objects 標誌處理其 commit 引數來構建其輸出的物件列表的方式相同。結果列表中的物件將被打包。除了修訂,--not--shallow <SHA-1> 行也接受。

--unpacked

這隱含了 --revs。在處理從標準輸入讀取的修訂引數列表時,將打包的物件限制為那些尚未打包的物件。

--all

這隱含了 --revs。除了從標準輸入讀取的修訂引數列表外,還會假定 refs/ 下的所有引用都指定為包含在內。

--include-tag

如果它們引用的物件已包含在生成的 packfile 中,則包含未請求的註釋標籤。這對於將新標籤傳送到原生 Git 客戶端可能很有用。

--stdin-packs[=<mode>]

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

mode 為 "follow" 時,來自未列出 pack 的物件將受到特殊處理。如果一個物件(1)可從包含的 pack 中訪問,並且(2)不在任何已排除的 pack 中,則該物件將被包含。此模式對於例如恢復 cruft pack 中一度不可訪問的物件以生成 pack 非常有用,這些 pack 在已排除 pack 設定的邊界內是可訪問的。

--revs 或隱含 --revs 的選項(例如 --all)不相容,但與 --unpacked 相容。

--cruft

將不可訪問的物件打包到一個單獨的“cruft” pack 中,透過存在一個 .mtimes 檔案來表示。通常由 git repack --cruft 使用。呼叫者提供 pack 名稱列表,並指示哪些 pack 將保留在倉庫中,以及哪些 pack 將被刪除(由 - 字首指示)。cruft pack 的內容是所有不包含在已保留 pack 中且未超過寬限期(請參閱下面的 --cruft-expiration)的物件,或者已超過寬限期但可從尚未超過寬限期的其他物件訪問的物件。

當輸入列表包含一個 pack,該 pack 包含所有可訪問物件(並將所有其他 pack 列為待刪除)時,相應的 cruft pack 將包含所有不可訪問的物件(mtime 新於 --cruft-expiration)以及任何 mtime 舊於 --cruft-expiration 但可從 mtime 新於 --cruft-expiration 的不可訪問物件的可訪問物件。

--unpack-unreachable--keep-unreachable--pack-loose-unreachable--stdin-packs 以及任何隱含 --revs 的選項不相容。

--cruft-expiration=<approxidate>

如果指定,則從 cruft pack 中刪除 mtime 早於 <approxidate> 的物件。如果未指定(且給出了 --cruft),則不會刪除任何物件。

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

這兩個選項會影響 pack 中包含的物件如何使用 delta 壓縮儲存。物件首先按型別、大小和可選名稱進行內部排序,並與 --window 內的其他物件進行比較,以檢視使用 delta 壓縮是否可以節省空間。--depth 限制了最大 delta 深度;過深的 delta 會影響解包器的效能,因為 delta 資料需要多次應用才能獲得所需的物件。

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

--window-memory=<n>

此選項在 --window 之上提供了額外的限制;視窗大小將動態縮放,以不超過 <n> 位元組記憶體。這在包含大量和大物件混合的儲存庫中很有用,以避免使用大視窗時耗盡記憶體,同時仍能利用大視窗處理小物件。大小可以後綴 "k"、"m" 或 "g"。 --window-memory=0 使記憶體使用不受限制。預設值取自 pack.windowMemory 配置變數。

--max-pack-size=<n>

在不尋常的情況下,您可能無法在檔案系統上建立大於特定大小的檔案,此選項可用於告訴命令將輸出 packfile 分割成多個獨立的 packfile,每個 packfile 不大於給定大小。大小可以後綴 "k"、"m" 或 "g"。允許的最小大小限制為 1 MiB。預設是不限制,除非設定了配置變數 pack.packSizeLimit。請注意,此選項可能會導致儲存庫更大且更慢;請參閱 pack.packSizeLimit 中的討論。

--honor-pack-keep

此標誌會忽略物件是否已存在於本地 pack 中並具有 .keep 檔案,即使它原本會被打包。

--keep-pack=<pack-name>

此標誌會忽略物件是否已存在於指定的 pack 中,即使它原本會被打包。 <pack-name> 是 pack 檔名,不帶前導目錄(例如 pack-123.pack)。可以多次指定該選項以保留多個 pack。

--incremental

此標誌會忽略物件是否已存在於 pack 中,即使它原本會被打包。

--local

此標誌會忽略從備用物件儲存借用的物件,即使它原本會被打包。

--non-empty

僅當打包歸檔包含至少一個物件時才建立它。

--progress

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

--all-progress

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

--all-progress-implied

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

-q

此標誌使命令不報告標準錯誤流上的進度。

--no-reuse-delta

在倉庫中建立打包歸檔時,如果存在現有 pack,命令會重用現有的 delta 以避免即時搜尋新的 delta。這有時會導致 pack 稍有欠佳。此標誌告訴命令不要重用現有 delta,而是從頭開始計算它們。

--no-reuse-object

此標誌告訴命令完全不重用現有的物件資料,包括非 delta 物件,強制重新壓縮所有內容。這隱含了 --no-reuse-delta。僅在需要對打包資料進行整體強制不同壓縮級別的情況下使用。

--compression=<n>

指定生成 pack 中新壓縮資料的壓縮級別。如果未指定,pack 壓縮級別首先由 pack.compression 確定,然後由 core.compression 確定,如果兩者都未設定,則預設為 -1(zlib 預設值)。新增 --no-reuse-object 以強制對所有資料使用統一的壓縮級別,無論其來源如何。

--sparse
--no-sparse

切換 "sparse" 演算法來確定在組合使用 "--revs" 選項時要包含在 pack 中的物件。此演算法僅遍歷引入新物件的路徑中出現的樹。在計算要傳送小型更改的 pack 時,這可以帶來顯著的效能優勢。但是,如果包含的提交包含某些型別的直接重新命名,則可能會有額外的物件被新增到 pack-file 中。如果未包含此選項,則預設為 pack.useSparse 的值,該值為 true,除非另有指定。

--thin

透過省略傳送方和接收方之間的公共物件來建立“thin” pack,以減少網路傳輸。此選項僅在與 --stdout 結合使用時才有意義。

注意:thin pack 透過省略必需的物件來違反打包歸檔格式,因此在不使其自包含的情況下無法被 Git 使用。使用 git index-pack --fix-thin(請參閱 git-index-pack[1])來恢復自包含屬性。

--shallow

最佳化將提供給客戶端的 shallow repository 的 pack。此選項與 --thin 結合使用,可以以速度為代價獲得更小的 pack。

--delta-base-offset

打包歸檔可以將 delta 的基物件表示為 20 位元組的物件名稱或流中的偏移量,但舊版本的 Git 不理解後者。預設情況下,git pack-objects 為了更好的相容性只使用前者。此選項允許命令使用後者來減小尺寸。根據平均 delta 鏈長度,此選項通常會使生成的 packfile 縮小 3-5%。

注意:porcelain 命令,如 git gc(請參閱 git-gc[1])、git repack(請參閱 git-repack[1])在將物件打包到 pack 檔案時,在現代 Git 中預設會傳遞此選項。 git bundle(請參閱 git-bundle[1])在建立 bundle 時也會。

--threads=<n>

指定生成執行緒數量來搜尋最佳 delta 匹配。這要求 pack-objects 使用 pthreads 進行編譯,否則此選項將被忽略併發出警告。目的是減少多處理器機器上的打包時間。但是,delta 搜尋視窗所需的記憶體量會乘以執行緒數。指定 0 將導致 Git 自動檢測 CPU 數量並相應地設定執行緒數。

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

這僅供測試套件使用。它允許強制生成 pack 索引的版本,並強制 64 位索引條目應用於給定偏移量以上的物件。

--keep-true-parents

使用此選項,即使父母被 grafts 隱藏,也會被打包。

--filter=<filter-spec>

從生成的 packfile 中省略某些物件(通常是 blobs)。請參閱 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 檔案的 pack 中的物件外,還會將 --unpacked= 選項命名的 pack 中的引用所無法訪問的物件新增到結果 pack 中。這隱含了 --revs

--pack-loose-unreachable

打包不可訪問的 loose 物件(並移除它們的 loose 對等體)。這隱含了 --revs

--unpack-unreachable

將不可訪問的物件保留為 loose 形式。這隱含了 --revs

--delta-islands

根據“islands”(島嶼)限制 delta 匹配。請參閱下面的 DELTA ISLANDS。

--name-hash-version=<n>

在執行 delta 壓縮時,Git 會根據啟發式方法使用物件的路徑來對可能相似的物件進行分組。雖然按精確路徑匹配分組物件對於具有許多版本的路徑很有用,但在查詢跨不同完整路徑的 delta 對時也有好處。Git 按型別收集物件,然後按路徑的“名稱雜湊”分組,再按大小分組,希望能將能夠很好地壓縮的物件組合在一起。

預設的名稱雜湊版本是 1,它透過考慮路徑的最後位元組作為對雜湊函式提供最大幅度來優先考慮雜湊區域性性。此版本在區分短路徑和查詢跨目錄的重新命名方面表現出色。然而,雜湊函式主要依賴於路徑的最後 16 個位元組。如果儲存庫中有許多路徑具有相同的最後 16 個位元組,並且僅在父目錄上有所不同,那麼此名稱雜湊可能會導致過多的衝突並導致結果不佳。目前,在寫入具有 --write-bitmap-index 的可訪問性點陣圖檔案時,需要此版本。

名稱雜湊版本 2 具有與版本 1 相似的區域性性特徵,但它分別考慮每個路徑元件,並透過移位疊加雜湊。這仍然優先考慮路徑的最後位元組,但還透過父目錄名稱“加鹽”雜湊的低位。此方法允許保留版本 1 的一些區域性性優勢,同時打破了在許多不同目錄中出現的相似命名檔案的大多數衝突。目前,在寫入具有 --write-bitmap-index 的可訪問性點陣圖檔案時,不允許使用此版本,它將被自動更改為版本 1

--path-walk

透過首先按路徑組織物件,然後進行第二次跨路徑正常壓縮來執行壓縮。這有可能改善 delta 壓縮,尤其是在檔名導致 Git 預設名稱雜湊演算法發生衝突的情況下。

--delta-islands--shallow--filter 不相容。在存在 --path-walk 的情況下,--use-bitmap-index 選項將被忽略。

Delta 島嶼

在可能的情況下,pack-objects 會嘗試重用現有的磁碟 delta,以避免即時搜尋新的 delta。這是服務 fetches 的一項重要最佳化,因為它意味著伺服器可以避免解壓大部分物件,而只需直接從磁碟傳送位元組。當一個物件作為 delta 儲存在一個接收方沒有(並且我們還沒有傳送)的基物件上時,此最佳化無法生效。在這種情況下,伺服器會“破壞”delta,必須尋找一個新的,這會帶來很高的 CPU 成本。因此,對於效能來說,磁碟 delta 關係中的物件集與客戶端將要獲取的物件集相匹配非常重要。

在一個普通的儲存庫中,這通常會自動實現。物件大多可從分支和標籤訪問,這也是客戶端獲取的內容。在伺服器上找到的任何 delta 都可能是在客戶端擁有或將要擁有的物件之間。

但在某些儲存庫設定中,您可能擁有多個相關但獨立的 ref 尖端組,而客戶端傾向於獨立地獲取這些組。例如,假設您在一個共享物件儲存中託管一個儲存庫的多個“fork”,並透過 GIT_NAMESPACE 或使用 alternates 機制的獨立儲存庫允許客戶端將它們視為單獨的儲存庫。一個樸素的 repack 可能會發現一個物件的最佳 delta 是針對只存在於另一個 fork 中的基物件。但是當客戶端獲取時,他們將沒有基物件,我們必須即時尋找一個新的 delta。

如果您在 refs/heads/refs/tags/ 之外擁有許多指向相關物件的引用(例如,某些託管提供商使用的 refs/pullrefs/changes),則可能存在類似的情況。預設情況下,客戶端僅獲取 heads 和 tags,而針對僅存在於那些其他組中的物件的 delta 不能按原樣傳送。

Delta 島嶼透過允許您將 ref 分組到不同的“島嶼”來解決此問題。Pack-objects 計算哪些物件可從哪些島嶼訪問,並拒絕從一個物件 A 建立一個 delta,其基物件不存在於 A 的所有島嶼中。這會導致 pack 稍大(因為我們錯過了一些 delta 機會),但保證獲取一個島嶼不會因為跨越島嶼邊界而需要即時重新計算 delta。

在與 delta 島嶼一起 repack 時,delta 視窗傾向於被配置所禁止的候選者堵塞。使用大的 --window 進行 repack 有所幫助(並且由於我們可以基於島嶼在任何計算之前拒絕一些物件對,因此花費的時間不會像其他情況那樣長)。

島嶼透過 pack.island 選項進行配置,該選項可以重複指定。每個值都是一個左錨定的正則表示式,匹配 refname。例如

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

將 heads 和 tags 放入一個島嶼(其名稱為空字串;有關命名,請參閱下文)。任何不匹配這些正則表示式的 ref(例如 refs/pull/123)都不在任何島嶼中。因此,僅從 refs/pull/(而不是 heads 或 tags)訪問的任何物件都不是 refs/heads/ 的基物件的候選。

Ref 根據其“名稱”分組到島嶼中,並且產生相同名稱的兩個正則表示式被視為屬於同一個島嶼。名稱是從正則表示式透過連線正則表示式的任何捕獲組計算得出的,捕獲組之間用破折號 - 分隔。(如果沒有捕獲組,則名稱為空字串,如上例所示。)這允許您建立任意數量的島嶼。但最多支援 14 個此類捕獲組。

例如,假設您將每個 fork 的 ref 儲存在 refs/virtual/ID 中,其中 ID 是一個數字識別符號。然後,您可以配置

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

這將每個 fork 的 heads 和 tags 放入它們自己的島嶼(名稱為“1234”或類似名稱),並將每個 fork 的 pull refs 放入它們自己的“1234-pull”島嶼。

請注意,我們為每個正則表示式選擇一個島嶼,使用“後一個優先”的順序(這允許倉庫特定的配置優先於使用者範圍的配置,依此類推)。

配置

各種配置變數會影響打包,請參閱 git-config[1](搜尋“pack”和“delta”)。

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

GIT

Git[1] 套件的一部分