日本語 ▾ トピック ▾ 最新バージョン ▾ gitformat-pack 最終更新: 2.44.0

名前

gitformat-pack - Git パック形式

概要

$GIT_DIR/objects/pack/pack-.{pack,idx}
$GIT_DIR/objects/pack/pack-.rev
$GIT_DIR/objects/pack/pack-*.mtimes
$GIT_DIR/objects/pack/multi-pack-index

説明

Git パック形式は、Git がほとんどの主要なリポジトリデータを格納する方法です。リポジトリの存続期間中に、ゆるいオブジェクト (もしあれば) や小さなパックがより大きなパックに統合されます。git-gc[1] および git-pack-objects[1] を参照してください。

パック形式は、ワイヤー上でも使用されます (例: gitprotocol-v2[5] を参照)。また、gitformat-bundle[5] の場合は、他のコンテナ形式の一部でもあります。

チェックサムとオブジェクトID

従来のSHA-1を使用するリポジトリでは、以下に述べるパックのチェックサム、インデックスのチェックサム、オブジェクトID(オブジェクト名)はすべてSHA-1を使用して計算されます。同様に、SHA-256リポジトリでは、これらの値はSHA-256を使用して計算されます。

pack-*.pack ファイルは以下のフォーマットを持っています。

  • ヘッダーが最初に現れ、以下の要素から構成されます。

    4-byte signature:
        The signature is: {'P', 'A', 'C', 'K'}
       4-byte version number (network byte order):
    Git currently accepts version number 2 or 3 but
           generates version 2 only.
    4-byte number of objects contained in the pack (network byte order)
    Observation: we cannot have more than 4G versions ;-) and
    more than 4G objects in a pack.
  • ヘッダーの後には、多数のオブジェクトエントリが続きます。各エントリは次のようになります。

    (undeltified representation)
    n-byte type and length (3-bit type, (n-1)*7+4-bit length)
    compressed data
       (deltified representation)
       n-byte type and length (3-bit type, (n-1)*7+4-bit length)
       base object name if OBJ_REF_DELTA or a negative relative
    offset from the delta object's position in the pack if this
    is an OBJ_OFS_DELTA object
       compressed delta data
    Observation: the length of each object is encoded in a variable
    length format and is not constrained to 32-bit or anything.
  • トレーラーには、上記のすべてのパックチェックサムが記録されます。

オブジェクトの種類

有効なオブジェクトの種類は以下の通りです

  • OBJ_COMMIT (1)

  • OBJ_TREE (2)

  • OBJ_BLOB (3)

  • OBJ_TAG (4)

  • OBJ_OFS_DELTA (6)

  • OBJ_REF_DELTA (7)

タイプ5は将来の拡張のために予約されています。タイプ0は無効です。

サイズエンコーディング

この文書では、非負整数に対して以下の「サイズエンコーディング」を使用します。各バイトから、下位7ビットが結果の整数を形成するために使用されます。最上位ビットが1である限り、このプロセスが続行されます。MSBが0のバイトは最後の7ビットを提供します。7ビットのチャンクは連結されます。後の値がより重要です。

このサイズエンコーディングは、この文書でも使用されている「オフセットエンコーディング」と混同しないでください。

デルタ化された表現

概念的には、コミット、ツリー、タグ、ブロブの4つのオブジェクトタイプしかありません。しかし、スペースを節約するために、オブジェクトは別の「ベース」オブジェクトの「デルタ」として格納されることがあります。これらの表現には、ofs-deltaとref-deltaという新しいタイプが割り当てられ、これらはパックファイル内でのみ有効です。

ofs-deltaとref-deltaはどちらも、オブジェクトを再構築するために別のオブジェクト(*ベースオブジェクト*と呼ばれる)に適用される「デルタ」を格納します。両者の違いは、ref-deltaがベースオブジェクト名を直接エンコードするのに対し、ベースオブジェクトが同じパックにある場合、ofs-deltaはパック内のベースオブジェクトのオフセットをエンコードするという点です。

ベースオブジェクトが同じパックにある場合、それもデルタ化される可能性があります。Ref-deltaはパック外のオブジェクト(いわゆる「シンパック」)を参照することもできます。ただし、ディスクに保存される場合、循環依存を避けるためにパックは自己完結型である必要があります。

デルタデータは、ベースオブジェクトのサイズと再構築されるオブジェクトのサイズから始まります。これらのサイズは上記のサイズエンコーディングを使用してエンコードされます。デルタデータの残りの部分は、ベースオブジェクトからオブジェクトを再構築するための命令のシーケンスです。ベースオブジェクトがデルタ化されている場合、まず正規形式に変換する必要があります。各命令は、完了するまでターゲットオブジェクトにデータをどんどん追加します。これまでにサポートされている命令は2つです。ソースオブジェクトからバイト範囲をコピーするための命令と、命令自体に埋め込まれた新しいデータを挿入するための命令です。

各命令は可変長です。命令タイプは、最初のオクテットの7番目のビットによって決定されます。以下の図は、RFC 1951 (Deflate圧縮データ形式) の慣例に従います。

ベースオブジェクトからコピーする命令

+----------+---------+---------+---------+---------+-------+-------+-------+
| 1xxxxxxx | offset1 | offset2 | offset3 | offset4 | size1 | size2 | size3 |
+----------+---------+---------+---------+---------+-------+-------+-------+

これは、ソースオブジェクトからバイト範囲をコピーするための命令形式です。コピー元のオフセットとコピーするバイト数をエンコードします。オフセットとサイズはリトルエンディアン順です。

すべてのオフセットおよびサイズバイトはオプションです。これは、小さなオフセットやサイズをエンコードする際の命令サイズを減らすためです。最初のオクテットの最初の7ビットは、次の7つのオクテットのどれが存在するかを決定します。ビット0が設定されている場合、offset1が存在します。ビット1が設定されている場合、offset2が存在します。

よりコンパクトな命令では、オフセットとサイズのエンコーディングは変更されないことに注意してください。たとえば、以下のようにoffset2のみが省略された場合でも、offset3はビット16-23を含みます。offset1のすぐ隣にあっても、offset2になり、ビット8-15を含むことはありません。

+----------+---------+---------+
| 10000101 | offset1 | offset3 |
+----------+---------+---------+

最もコンパクトな形式では、この命令は1バイト(0x80)しか占めず、オフセットとサイズは両方とも省略され、デフォルト値はゼロになります。もう1つの例外は、サイズゼロが自動的に0x10000に変換されることです。

新しいデータを追加する命令

+----------+============+
| 0xxxxxxx |    data    |
+----------+============+

これは、ベースオブジェクトなしでターゲットオブジェクトを構築するための命令です。以下のデータがターゲットオブジェクトに付加されます。最初のオクテットの最初の7ビットは、データのバイト単位のサイズを決定します。サイズはゼロ以外でなければなりません。

予約済み命令

+----------+============
| 00000000 |
+----------+============

これは将来の拡張のために予約されている命令です。

オリジナル (バージョン1) の pack-*.idx ファイルは以下のフォーマットを持ちます。

  • ヘッダーは、256個の4バイトネットワークバイトオーダー整数で構成されます。このテーブルのN番目のエントリは、対応するパック内のオブジェクトの数を記録し、そのオブジェクト名の最初のバイトはN以下です。これは*ファーストレベルのファンアウト*テーブルと呼ばれます。

  • ヘッダーの後に、パック内のオブジェクトごとに1つのエントリからなる、ソートされた24バイトエントリが続きます。各エントリは次のとおりです。

    4-byte network byte order integer, recording where the
    object is stored in the packfile as the offset from the
    beginning.
    one object name of the appropriate size.
  • ファイルはトレーラーで締めくくられます

    A copy of the pack checksum at the end of the corresponding
    packfile.
    Index checksum of all of the above.

パックインデックスファイル

	--  +--------------------------------+
fanout	    | fanout[0] = 2 (for example)    |-.
table	    +--------------------------------+ |
	    | fanout[1]                      | |
	    +--------------------------------+ |
	    | fanout[2]                      | |
	    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
	    | fanout[255] = total objects    |---.
	--  +--------------------------------+ | |
main	    | offset                         | | |
index	    | object name 00XXXXXXXXXXXXXXXX | | |
table	    +--------------------------------+ | |
	    | offset                         | | |
	    | object name 00XXXXXXXXXXXXXXXX | | |
	    +--------------------------------+<+ |
	  .-| offset                         |   |
	  | | object name 01XXXXXXXXXXXXXXXX |   |
	  | +--------------------------------+   |
	  | | offset                         |   |
	  | | object name 01XXXXXXXXXXXXXXXX |   |
	  | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   |
	  | | offset                         |   |
	  | | object name FFXXXXXXXXXXXXXXXX |   |
	--| +--------------------------------+<--+
trailer	  | | packfile checksum              |
	  | +--------------------------------+
	  | | idxfile checksum               |
	  | +--------------------------------+
          .-------.
                  |
Pack file entry: <+
    packed object header:
1-byte size extension bit (MSB)
       type (next 3 bit)
       size0 (lower 4-bit)
       n-byte sizeN (as long as MSB is set, each 7-bit)
	size0..sizeN form 4+7+7+..+7 bit integer, size0
	is the least significant part, and sizeN is the
	most significant part.
    packed object data:
       If it is not DELTA, then deflated bytes (the size above
	is the size before compression).
If it is REF_DELTA, then
  base object name (the size above is the
	size of the delta data that follows).
         delta data, deflated.
If it is OFS_DELTA, then
  n-byte offset (see below) interpreted as a negative
	offset from the type-byte of the header of the
	ofs-delta entry (the size above is the size of
	the delta data that follows).
  delta data, deflated.
  offset encoding:
n bytes with MSB set in all but the last one.
The offset is then the number constructed by
concatenating the lower 7 bit of each byte, and
for n >= 2 adding 2^7 + 2^14 + ... + 2^(7*(n-1))
to the result.

バージョン2のpack-*.idxファイルは4 GiBを超えるパックに対応し、さらに

have some other reorganizations.  They have the format:
  • 4バイトのマジックナンバー \377tOc。これは不合理なファンアウト[0]値です。

  • 4バイトのバージョン番号 (= 2)

  • V1と同様の256エントリのファンアウトテーブル。

  • ソートされたオブジェクト名テーブル。特定のオブジェクト名のバイナリ検索のキャッシュフットプリントを減らすために、オフセット値なしでパックされています。

  • パックされたオブジェクトデータの4バイトCRC32値のテーブル。これはV2で追加されたため、データ破損が検出されずに再パック中に圧縮データをパックからパックへ直接コピーできます。

  • 4バイトのオフセット値(ネットワークバイトオーダー)のテーブル。これらは通常31ビットのパックファイルオフセットですが、大きいオフセットはmsbitがセットされた次のテーブルへのインデックスとしてエンコードされます。

  • 8バイトのオフセットエントリのテーブル (2 GiB未満のパックファイルの場合は空)。パックファイルは頻繁に使用されるオブジェクトが前方になるように整理されているため、ほとんどのオブジェクト参照はこのテーブルを参照する必要はありません。

  • v1パックファイルと同じトレーラー

    A copy of the pack checksum at the end of the
    corresponding packfile.
    Index checksum of all of the above.

pack-*.rev ファイルのフォーマット

  • 4バイトのマジックナンバー 0x52494458 (RIDX)。

  • 4バイトのバージョン識別子 (= 1)。

  • 4バイトのハッシュ関数識別子 (= SHA-1の場合は1、SHA-256の場合は2)。

  • インデックス位置のテーブル(パックされたオブジェクトごとに1つ、合計 num_objects、それぞれ4バイトの符号なし整数、ネットワークオーダー)。これらはパックファイル内の対応するオフセットでソートされています。

  • トレーラーには、

    checksum of the corresponding packfile, and
    a checksum of all of the above.

すべての4バイトの数値はネットワークオーダーです。

pack-*.mtimes ファイルの形式

すべての4バイトの数値はネットワークバイトオーダーです。

  • 4バイトのマジックナンバー 0x4d544d45 (MTME)。

  • 4バイトのバージョン識別子 (= 1)。

  • 4バイトのハッシュ関数識別子 (= SHA-1の場合は1、SHA-256の場合は2)。

  • 4バイトの符号なし整数のテーブル。i番目の値は、対応するパック内のi番目のオブジェクトの変更時間(mtime)を、辞書順(インデックス)で表したものです。mtimeは標準エポック秒でカウントされます。

  • トレーラーには、対応するパックファイルのチェックサムと、上記のすべてのチェックサム(それぞれ指定されたハッシュ関数に従った長さを持つ)が含まれます。

マルチパックインデックス (MIDX) ファイルは以下のフォーマットを持っています。

マルチパックインデックスファイルは、複数のパックファイルとルーズオブジェクトを参照します。

MIDX に追加データを加える拡張を可能にするため、本体を「チャンク」に整理し、本体の先頭にルックアップテーブルを提供します。ヘッダーには、パック数、ベース MIDX ファイル数、ハッシュ長とタイプなどの特定の長さ値が含まれます。

すべての4バイトの数値はネットワークオーダーです。

ヘッダー

4-byte signature:
    The signature is: {'M', 'I', 'D', 'X'}
1-byte version number:
    Git only writes or recognizes version 1.
1-byte Object Id Version
    We infer the length of object IDs (OIDs) from this value:
	1 => SHA-1
	2 => SHA-256
    If the hash type does not match the repository's hash algorithm,
    the multi-pack-index file should be ignored with a warning
    presented to the user.
1-byte number of "chunks"
1-byte number of base multi-pack-index files:
    This value is currently always zero.
4-byte number of pack files

チャンクルックアップ

(C + 1) * 12 bytes providing the chunk offsets:
    First 4 bytes describe chunk id. Value 0 is a terminating label.
    Other 8 bytes provide offset in current file for chunk to start.
    (Chunks are provided in file-order, so you can infer the length
    using the next chunk position if necessary.)
The CHUNK LOOKUP matches the table of contents from
the chunk-based file format, see gitformat-chunk[5].
The remaining data in the body is described one chunk at a time, and
these chunks may be given in any order. Chunks are required unless
otherwise specified.

チャンクデータ

Packfile Names (ID: {'P', 'N', 'A', 'M'})
    Store the names of packfiles as a sequence of NUL-terminated
    strings. There is no extra padding between the filenames,
    and they are listed in lexicographic order. The chunk itself
    is padded at the end with between 0 and 3 NUL bytes to make the
    chunk size a multiple of 4 bytes.
Bitmapped Packfiles (ID: {'B', 'T', 'M', 'P'})
    Stores a table of two 4-byte unsigned integers in network order.
    Each table entry corresponds to a single pack (in the order that
    they appear above in the `PNAM` chunk). The values for each table
    entry are as follows:
    - The first bit position (in pseudo-pack order, see below) to
      contain an object from that pack.
    - The number of bits whose objects are selected from that pack.
OID Fanout (ID: {'O', 'I', 'D', 'F'})
    The ith entry, F[i], stores the number of OIDs with first
    byte at most i. Thus F[255] stores the total
    number of objects.
OID Lookup (ID: {'O', 'I', 'D', 'L'})
    The OIDs for all objects in the MIDX are stored in lexicographic
    order in this chunk.
Object Offsets (ID: {'O', 'O', 'F', 'F'})
    Stores two 4-byte values for every object.
    1: The pack-int-id for the pack storing this object.
    2: The offset within the pack.
	If all offsets are less than 2^32, then the large offset chunk
	will not exist and offsets are stored as in IDX v1.
	If there is at least one offset value larger than 2^32-1, then
	the large offset chunk must exist, and offsets larger than
	2^31-1 must be stored in it instead. If the large offset chunk
	exists and the 31st bit is on, then removing that bit reveals
	the row in the large offsets containing the 8-byte offset of
	this object.
[Optional] Object Large Offsets (ID: {'L', 'O', 'F', 'F'})
    8-byte offsets into large packfiles.
[Optional] Bitmap pack order (ID: {'R', 'I', 'D', 'X'})
    A list of MIDX positions (one per object in the MIDX, num_objects in
    total, each a 4-byte unsigned integer in network byte order), sorted
    according to their relative bitmap/pseudo-pack positions.

トレーラー

Index checksum of the above contents.

マルチパックインデックス逆インデックス

パックベースの逆インデックスと同様に、マルチパックインデックスも逆インデックスの生成に使用できます。

この逆インデックスは、オフセット、パック、インデックス位置の間をマッピングするのではなく、MIDX内でのオブジェクトの位置と、MIDXが記述する擬似パック内でのそのオブジェクトの位置(つまり、マルチパック逆インデックスのi番目のエントリは、擬似パック順でのi番目のオブジェクトのMIDX位置を保持します)をマッピングします。

これらの順序の違いを明確にするために、マルチパック到達可能性ビットマップ(まだ存在しませんが、ここで目指しているものです)を考えてみましょう。各ビットはMIDX内のオブジェクトに対応する必要があるため、ビット位置からMIDX位置への効率的なマッピングが必要です。

一つの解決策は、ビットがMIDXによって格納されているOIDソートされたインデックス内で同じ位置を占めるようにすることです。しかし、OIDは事実上ランダムであるため、結果として得られる到達可能性ビットマップには局所性がなく、したがって圧縮効率が悪くなります。(これが、単一パックのビットマップが同じ目的で.idxの順序ではなくパックの順序を使用する理由です。)

したがって、パックの順序を中心としたMIDX全体の順序を定義したいと考えています。これははるかに優れた局所性(したがって、より効率的に圧縮されます)を持っています。MIDX内のすべてのパックを連結して作成された擬似パックを考えることができます。例えば、MIDXに3つのパック(a、b、c)があり、それぞれ10、15、20個のオブジェクトがあるとすると、次のようなオブジェクトの順序を想像できます。

|a,0|a,1|...|a,9|b,0|b,1|...|b,14|c,0|c,1|...|c,19|

ここで、パックの順序はMIDXのパックリストによって定義され、各パック内のオブジェクトの順序は実際のパックファイル内の順序と同じです。

パックのリストとそのオブジェクト数があれば、その擬似パックの順序を素朴に再構築できます(例:位置27のオブジェクトは(c,1)でなければなりません。なぜならパック「a」と「b」が25個のスロットを消費したからです)。しかし、落とし穴があります。オブジェクトはパック間で重複する可能性があり、その場合、MIDXはオブジェクトへのポインタを1つだけ格納します(したがって、ビットマップには1つのスロットのみが必要です)。

呼び出し元は、ビット位置の順序でオブジェクトを読み取ることで重複を自分で処理できますが、これはオブジェクトの数に比例して線形であり、通常のビットマップ検索にはあまりにも高価です。逆インデックスを構築することでこれを解決できます。逆インデックスはインデックスの論理的な逆であり、そのインデックスはすでに重複を削除しているからです。しかし、オンザフライで逆インデックスを構築するのは高価になる可能性があります。パックベースの逆インデックスのオンディスク形式がすでに存在するため、MIDXの擬似パックにもそれを再利用しましょう。

MIDXからのオブジェクトは、疑似パックを結合するために次のように順序付けられます。pack(o)は、oがMIDXによって選択されたパックを返し、パックの順序をその数値ID(MIDXによって格納される)に基づいて定義するとします。offset(o)は、pack(o)内のoのオブジェクトオフセットを返すとします。次に、o1o2を次のように比較します。

  • pack(o1)pack(o2)のどちらか一方が優先され、もう一方がそうでない場合、優先される方が最初にソートされます。

    (これは、MIDXビットマップがパック再利用メカニズムによってどのパックが使用されるべきかを決定できるようにする詳細です。なぜなら、ビット位置0にあるオブジェクトを含むパックをMIDXに尋ねることができるからです)。

  • もしpack(o1) ≠ pack(o2)であれば、パックIDに基づいて降順に2つのオブジェクトをソートします。

  • それ以外の場合、pack(o1) = pack(o2)であり、オブジェクトはパック順にソートされます(つまり、offset(o1) < offset(o2)の場合に限り、o1o2より前にソートされます)。

要するに、MIDXの擬似パックは、MIDXによって格納されたパック内のオブジェクトをパック順に並べ、パックをMIDX順に(優先パックを最初にして)配置した、重複排除された連結です。

MIDXの逆インデックスは、MIDX自体のオプションの *RIDX* チャンクに格納されます。

BTMP チャンク

ビットマップされたパックファイル(BTMP)チャンクは、マルチパックインデックスの到達可能性ビットマップ内のオブジェクトに関する追加情報をエンコードします。到達可能性ビットマップのために、MIDXからのオブジェクトは「擬似パック」順(上記参照)に配置されることを思い出してください。

上記の例から、パック「a」、「b」、「c」がそれぞれ10、15、20個のオブジェクトを持つと仮定します。擬似パック順では、これらは次のように配置されます。

|a,0|a,1|...|a,9|b,0|b,1|...|b,14|c,0|c,1|...|c,19|

単一パックのビットマップ(または同等に、優先パックを持つマルチパック到達可能性ビットマップ)で作業する場合、git-pack-objects[1] は「逐語的」な再利用を実行し、オブジェクトをパッキングリストに追加する代わりに、ビットマップされたパックファイルまたは優先パックファイルのチャンクを再利用しようとします。

既存のパックからバイトのチャンクが再利用される場合、その中に含まれるオブジェクトをパッキングリストに追加する必要がなく、メモリとCPU時間を節約できます。ただし、既存のパックファイルからのチャンクは、次の条件が満たされた場合にのみ再利用できます。

  • チャンクには、呼び出し元が要求したオブジェクトのみが含まれていること(つまり、呼び出し元が明示的または暗黙的に要求しなかったオブジェクトが含まれていないこと)。

  • オフセットまたは参照デルタとして非シンパックに格納されているすべてのオブジェクトも、結果のパックにそのベースオブジェクトを含みます。

BTMP チャンクは、上記で説明した一連のパックファイルにわたるマルチパック再利用を実装するために必要な情報をエンコードします。具体的には、BTMP チャンクは、MIDXに格納されている各パックファイル p について、3つの情報(すべて32ビットの符号なし整数、ネットワークバイトオーダー)を次のようにエンコードします。

bitmap_pos

マルチパックインデックスの到達可能性ビットマップ内で、p からのオブジェクトによって占められる最初のビット位置(擬似パック順)。

bitmap_nr

bitmap_pos のビット位置を含む、そのパック p からのオブジェクトをエンコードするビット位置の数。

たとえば、上記の例(パック「a」、「b」、「c」)に対応するBTMPチャンクは次のようになります。

bitmap_pos bitmap_nr

パックファイル「a」

0

10

パックファイル「b」

10

15

パックファイル「c」

25

20

この情報が揃っていれば、BTMP チャンクの実装以前に個々のパックに対して逐語的なパック再利用が行われていたのと同様に、各パックファイルを個別に再利用可能として扱うことができます。

クルフトパック

クルフトパック機能は、Git の到達不能オブジェクトを削除する従来のメカニズムに代わるものを提供します。このドキュメントでは、Git の剪定メカニズムの概要と、クルフトパックを使用して同じことを実現する方法を説明します。

背景

リポジトリから到達不能オブジェクトを削除するために、Gitはgit repack -Adgit-repack[1]を参照)を提供しています。ドキュメントからの引用です。

[...] unreachable objects in a previous pack become loose, unpacked objects,
instead of being left in the old pack. [...] loose unreachable objects will be
pruned according to normal expiry rules with the next 'git gc' invocation.

到達不能オブジェクトはすぐに削除されません。なぜなら、そうすると、削除されようとしているオブジェクトを参照する受信プッシュと競合する可能性があるからです。代わりに、それらの到達不能オブジェクトはルーズオブジェクトとして格納され、有効期限ウィンドウを過ぎるまでその状態を維持し、その時点でgit-prune[1]によって削除されます。

Gitは、オブジェクトごとのmtimeを追跡するために、これらの到達不能オブジェクトをルーズに格納する必要があります。これらの到達不能オブジェクトが1つの大きなパックに書き込まれた場合、そのパックを更新する(その中に含まれるオブジェクトが書き換えられたため)か、到達不能オブジェクトの新しいパックを作成すると、パックのmtimeが更新され、その中のオブジェクトは決して有効期限ウィンドウから外れることはありません。代わりに、オブジェクトは個々のオブジェクトmtimeを追跡し、すべてのクルフトオブジェクトが一度に更新される状況を避けるために、ルーズに格納されます。

これは、リポジトリに猶予期間をまだ過ぎていない到達不能オブジェクトが多数含まれている場合に、望ましくない状況を引き起こす可能性があります。.git/objectsのシャードに大きなディレクトリがあると、リポジトリのパフォーマンスが低下する可能性があります。しかし、十分な数の到達不能オブジェクトがあると、inodeの枯渇につながり、システム全体のパフォーマンスを低下させる可能性があります。これらのオブジェクトをパックできないため、これらのリポジトリはディスクスペースを大量に占めることがよくあります。なぜなら、それらをzlibで圧縮することしかできず、デルタチェーンに格納できないからです。

クルフトパック

クルフトパックは、すべてのルーズオブジェクトを含む単一のパックとともに、オブジェクトごとのmtimeを別のファイルに含めることで、到達不能オブジェクトをルーズな状態で格納する必要をなくします。

クルフトパックは、新しいパックを生成する際に git repack --cruft によって書き込まれます。git-pack-objects[1]--cruft オプション。git repack --cruft は従来のオールインワンリパックであり、結果のパック内のすべてが到達可能であり、それ以外のすべてが到達不能であることを意味します。一度書き込まれると、--cruft オプションは git repack に、前のステップでパックされなかったオブジェクトのみを含む別のパックを生成するように指示します(これは、すべての到達不能オブジェクトをまとめてパックすることに相当します)。これは次のように進行します。

  1. すべてのオブジェクトを列挙し、(a)保持されているパックに含まれていない、かつ(b)mtimeが猶予期間内であるオブジェクトをトラバーサルチップとしてマークします。

  2. 前のステップで収集されたヒントに基づいて到達可能性トラバーサルを実行し、途中のすべてのオブジェクトをパックに追加します。

  3. パックを書き出し、オブジェクトごとのタイムスタンプを記録する.mtimesファイルを一緒に書き出します。

このモードは、クルフトパックを書き込むように指示されたときにgit-repack[1]によって内部的に呼び出されます。重要なのは、インコアの保持されたパックのセットが、リパックによって削除されないパックのセットとまったく同じであることです。つまり、それらはリポジトリの到達可能なオブジェクトをすべて含んでいます。

リポジトリに既にクルフトパックがある場合、通常、git repack --cruft はオブジェクトを追加するだけです。git repack--cruft-expiration オプションが与えられた場合が例外です。これは、生成されたクルフトパックが期限切れのオブジェクトを省略することを可能にし、git-gc[1] が後でそれらのオブジェクトを期限切れにするのを待つ必要がなくなります。

期限切れの到達不能オブジェクトの削除は、通常、git-gc[1] が担当します。

代替案

この設計の注目すべき代替案には、次のものがあります。

  • オブジェクトごとのmtimeデータの場所。

mtimeデータの場所については、.idx形式を複雑にしないために、パックに紐付けられた新しい補助ファイルが選択されました。.idx形式がオプションのデータチャンクをサポートするようになれば、.mtimes形式を.idx自体に統合することも理にかなっているかもしれません。

GIT

git[1]スイートの一部

scroll-to-top