Gitオブジェクトディレクトリには、 パックファイル(packfiles)(接尾辞 .pack)とパックインデックス(pack-indexes)(接尾辞 .idx) を含む pack ディレクトリが含まれています。 パックインデックスは、オブジェクトを検索し、パック内のオフセットに移動する方法を提供しますが、これらはパックファイルとペアになっている必要があります。 パックインデクスはパックファイルの接尾辞のみが異なるため、このペアリングはファイル名によって異なります。 パックインデックスはパックファイルごとの高速ルックアップを提供しますが、略語はすべてのパックファイルを検査する必要があり、最近使用されたパックファイルを見逃す可能性が高いため、パックファイルの数が増えるとこのパフォーマンスは低下します。 一部の大規模なリポジトリでは、ストレージスペースや過剰な再パック時間のため、単一のパックファイルに再パックすることはできません。

multi-pack-index(略してMIDX)は、オブジェクトとそのオフセットのリストを複数のパックファイルに格納します。 以下を含みます:

  • パックファイル名のリスト。

  • オブジェクトIDのソートされたリスト。

  • 以下を含むi番目のオブジェクトIDのメタデータのリスト:

    • j番目のパックファイルを参照する値 j 。

    • オブジェクトのj番目のパックファイル内のオフセット。

  • 巨大なオフセットが必要な場合は、別の、バージョン2のパックインデックスと同様の巨大オフセットリストを使用します。

    • オプションの疑似パック順のオブジェクトのリスト(MIDX ビットマップで使用)。

したがって、我々は任意の数のパックファイルに対して O(log N) 回数でルックアップ可能です。

Design Details

  • MIDXは、 .git/objects/pack ディレクトリの multi-pack-index という名前のファイルに保存されます。 これは、代替のパックディレクトリに保存できます。 それは同じディレクトリ内のパックファイルのみを参照します。

  • MIDX ファイルを使用するには、core.multiPackIndex 構成設定をオン (デフォルト) にする必要があります。 false に設定すると、 Git は MIDX ファイルが存在する場合でも読み取れなくなります。

  • ファイル形式にはオブジェクトIDハッシュ関数のパラメーターが含まれているため、ハッシュアルゴリズムを将来変更しても、形式を変更する必要はありません。

  • MIDXは、オブジェクトIDごとに1つのレコードのみを保持します。 オブジェクトが複数のパックファイルに表示される場合、MIDXは優先パックファイル内のコピーを選択します。それ以外の場合は、最も最近に変更されたパックファイルから選択します。

  • MIDXに登録されていないpackディレクトリにパックファイルが存在する場合、それらのパックファイル は packed_git リスト と packed_git_mru キャッシュ にロードされます。

  • pack-indexes (.idx ファイル) はpackディレクトリに残っているため、MIDXファイルを削除したり、 core.midx を false に設定したり、情報を失うことなくダウングレードしたりできます。

  • MIDXファイル形式は、オプションのデータを追加できるチャンクベースのアプローチ(commit-graphファイルと同様)を使用します。

Future Work

  • multi-pack-indexを使用すると、(非常に大きなリポジトリなど、)特に再パックにコストがかかる場合、または(需要の高いビルドマシンなどで、)予期しないメンテナンス時間が許容できない場合に、多くのパックファイルを使用できます。 ただし、multi-pack-indexは毎回完全に書き直す必要があります。 フォーマットをインクリメンタルに拡張できるため、書き込みが高速になります。 大きな 「base」MIDXファイル を指す小さな 「tip」マルチパックインデックス を保存することで、オブジェクトのルックアップに必要なバイナリ検索の数を減らしながら、書き込みを高速に保つことができます。

  • multi-pack-indexが拡張されて「安定したオブジェクトの順序」(関数 Order(hash)= multi-pack-indexが更新されても、特定のハッシュに対して定数である整数)を格納する場合、MIDXとは独立して更新されるMIDXビットマップは以下のようになります。

  • パックファイルは、初期名を共有するが .pack.keep または .promisor に置き換える空のファイルを使用して「special」としてマークできます。 パックファイルに関する情報のフラグを記録するmulti-pack-indexにオプションのデータチャンクを追加できます。 これにより、「repacked」(再パック)や「redeltified」(再削除)などの新しいステータスが可能になり、マルチパック環境でのパックのメンテナンスに役立ちます。 パックファイルをオブジェクトタイプ(コミット、ツリー、ブロブなど)で整理し、このメタデータを使用してそのメンテナンスを支援することも役立つ場合があります。

[0] https://bugs.chromium.org/p/git/issues/detail?id=6 Chromium work item for: Multi-Pack Index (MIDX)

[2] https://lore.kernel.org/git/alpine.DEB.2.20.1803091557510.23109@alexmv-linux/ Git Merge 2018コントリビューターのサミットノート(MIDXの議論を含む)