Git
英語 ▾ トピック ▾ 最新バージョン ▾ bundle-uri は2.40.0で最後に更新されました

Gitバンドルは、packファイルと、参照のセットや(場合によっては空の)必要なコミットのセットを含むいくつかの追加メタデータを格納するファイルです。詳細については、git-bundle[1] および gitformat-bundle[5] を参照してください。

バンドルURIは、リモートから残りのオブジェクトをフェッチする前に、Gitがオブジェクトデータベースをブートストラップするために1つ以上のバンドルをダウンロードできる場所です。

1つの目標は、オリジンサーバーへのネットワーク接続が貧弱なユーザーのクローンとフェッチを高速化することです。もう1つの利点は、CIビルドファームなどのヘビーユーザーが、Gitデータの大部分にローカルリソースを使用できるようにすることで、オリジンサーバーの負荷を軽減することです。

バンドルURI機能を有効にするには、ユーザーはコマンドラインオプションを使用してバンドルURIを指定するか、オリジンサーバーはプロトコルv2機能を介して1つ以上のURIをアドバタイズできます。

設計目標

バンドルURI標準は、複数のワークロードに対応できるだけの柔軟性を備えることを目指しています。バンドルプロバイダーとGitクライアントは、バンドルURIを作成および消費する方法についていくつかの選択肢があります。

  • バンドルは、サーバーが希望する任意の名前を持つことができます。この名前は、バンドルコンテンツのハッシュを使用して、不変のデータを参照できます。ただし、これは、コンテンツが更新されるたびに新しいURIが必要になることを意味します。これは、サーバーがURIをアドバタイズしている場合(およびサーバーが新しいバンドルが生成されていることを認識している場合)は許容される可能性がありますが、コマンドラインオプションを使用するユーザーにとっては人間工学に基づいたものではありません。

  • バンドルは、完全なクローンをブートストラップするために特別に編成できますが、増分フェッチをブートストラップすることを目的として編成することもできます。バンドルプロバイダーは、増分フェッチ中のクライアントのダウンロードを最小限に抑えるために、いくつかの編成スキームのいずれかを選択する必要がありますが、Gitクライアントは、これらの操作のいずれかにバンドルを使用するかどうかを選択することもできます。

  • バンドルプロバイダーは、完全なクローン、部分的なクローン、またはその両方をサポートすることを選択できます。クライアントは、リポジトリの部分クローンフィルター(存在する場合)に適したバンドルを検出できます。

  • バンドルプロバイダーは、単一のバンドル(クローン専用)またはバンドルのリストを使用できます。バンドルのリストを使用する場合、プロバイダーは、クライアントが完全なクローンに*すべて*のバンドルURIを必要とするか、*いずれか* 1つのバンドルURIで十分であるかを指定できます。これにより、バンドルプロバイダーは異なる地域に異なるURIを使用できます。

  • バンドルプロバイダーは、作成トークンなどのヒューリスティックを使用してバンドルを編成し、クライアントが不要なバンドルをダウンロードするのを防ぐのに役立てることができます。バンドルプロバイダーがこれらのヒューリスティックを提供しない場合、クライアントは最適化を使用してダウンロードされるデータ量を最小限に抑えることができます。

  • バンドルプロバイダーは、Gitサーバーに関連付けられている必要はありません。クライアントは、Gitサーバーによってアドバタイズされなくても、バンドルプロバイダーを使用することを選択できます。

  • クライアントは、Gitサーバーによってアドバタイズされているバンドルプロバイダーを検出することを選択できます。これは、 `git clone` 中、 `git fetch` 中、その両方、またはどちらでもない場合に発生する可能性があります。ユーザーは、自分に最適な組み合わせを選択できます。

  • クライアントは、いつでも手動でバンドルプロバイダーを設定することを選択できます。クライアントは、 `git clone` へのコマンドラインオプションとしてバンドルプロバイダーを手動で指定することもできます。

各リポジトリは異なり、すべてのGitサーバーには異なるニーズがあります。バンドルURI機能は、すべてのニーズを満たすのに十分な柔軟性があることを願っています。そうでない場合、機能はそのバージョン管理メカニズムを通じて拡張できます。

サーバー要件

バンドルサーバーのサーバー側実装を提供するために、Gitプロトコルの他の部分は必要ありません。これにより、サーバー管理者は、CDNなどの静的コンテンツソリューションを使用してバンドルファイルを提供できます。

バンドルURI機能の現在のスコープでは、すべてのURIは、そのURLへの `GET` リクエストを使用してコンテンツがローカルファイルにダウンロードされるHTTP(S)URLであると予想されます。サーバーは、安全なアクセスのための構成済みの認証情報ヘルパーをトリガーすることを目的として、これらのリクエストに認証要件を含めることができます。(将来の拡張では、「file://」URIまたはSSH URIを使用できます。)

サーバーからの `200 OK` 応答を想定すると、URLのコンテンツが検査されます。最初に、Gitはファイルをバージョン2以降のバンドルファイルとして解析しようとします。ファイルがバンドルでない場合、ファイルはGitの設定パーサーを使用してプレーンテキストファイルとして解析されます。その設定ファイルのキーと値のペアは、バンドルURIのリストを記述するものとします。これらの解析試行のいずれも成功しない場合、GitはユーザーにバンドルURIが誤ったデータを提供したというエラーを報告します。

サーバーによって提供されるその他のデータは、誤りであると見なされます.

バンドルリスト

Gitサーバーは、一連の `key = value` ペアを使用してバンドルURIをアドバタイズできます。バンドルURIは、これらの同じ `key = value` ペアを含むGit設定形式のプレーンテキストファイルを提供することもできます。どちらの場合も、これを*バンドルリスト*と見なします。ペアは、クライアントがどのバンドルをダウンロードし、どのバンドルを無視するかを決定するために使用できるバンドルに関する情報を指定します。

いくつかのキーは、リスト自体のプロパティに焦点を当てています。

bundle.version

(必須)この値は、バンドルリストのバージョン番号を提供します。将来のGitの変更により、Gitクライアントがバンドルリストファイルの新しいキーに反応する必要がある機能が有効になった場合、このバージョンは増加します。現在のバージョン番号は1のみであり、他の値が指定されている場合、Gitはこのファイルを使用できません。

bundle.mode

(必須)この値には、 `all` と `any` の2つの値のいずれかがあります。 `all` が指定されている場合、クライアントは、リポジトリの要件に一致するすべてのリストされたバンドルURIが必要になると予想する必要があります。 `any` が指定されている場合、クライアントは、リポジトリの要件に一致するバンドルURIのいずれか1つで十分であると予想する必要があります。通常、 `any` オプションは、異なる地域にある多数の異なるバンドルサーバーをリストするために使用されます。

bundle.heuristic

この文字列値のキーが存在する場合、バンドルリストは増分 `git fetch` コマンドでうまく機能するように設計されています。ヒューリスティックは、クライアントがダウンロードするバンドルのサブセットを決定するのに役立つ追加のキーが各バンドルで使用可能であることを示しています.現在計画されているヒューリスティックは `creationToken` のみです.

残りのキーには、各使用可能なバンドルのサーバー指定名である `<id>` セグメントが含まれています。 `<id>` には、英数字と `-` 文字のみを含める必要があります。

bundle.<id>.uri

(必須)この文字列値は、バンドル `<id>` をダウンロードするためのURIです。 URIがプロトコル( `http://` または `https://`)で始まる場合、URIは絶対パスです。それ以外の場合、URIはバンドルリストに使用されるURIを基準として解釈されます。 URIが `/` で始まる場合、その相対パスはバンドルリストに使用されるドメイン名を基準とします。(相対パスのこの使用法は、多数のサーバーまたは異なるドメイン名を持つCDNにバンドルのセットを配布しやすくすることを目的としています。)

bundle.<id>.filter

この文字列値は、このバンドルのヘッダーにも表示される必要があるオブジェクトフィルターを表します。サーバーはこの値を使用して、クライアントがオブジェクトフィルターに一致するものを選択できるさまざまな種類のバンドルを区別します.

bundle.<id>.creationToken

この値は、バンドルリストのソートに使用される負でない64ビット整数です。これは、 `bundle.heuristic = creationToken` の場合にフェッチ中にバンドルのサブセットをダウンロードするために使用されます。

bundle.<id>.location

この文字列値は、バンドルURIが提供される実際の場所をアドバタイズします。これは、ユーザーにどのバンドルURIを使用するかを選択肢を提示したり、GitによってどのバンドルURIが選択されたかを示す情報として使用したりできます。これは、 `bundle.mode` が `any` の場合にのみ有効です。

Git設定形式を使用したバンドルリストの例を次に示します

[bundle]
	version = 1
	mode = all
	heuristic = creationToken
[bundle "2022-02-09-1644442601-daily"]
	uri = https://bundles.example.com/git/git/2022-02-09-1644442601-daily.bundle
	creationToken = 1644442601
[bundle "2022-02-02-1643842562"]
	uri = https://bundles.example.com/git/git/2022-02-02-1643842562.bundle
	creationToken = 1643842562
[bundle "2022-02-09-1644442631-daily-blobless"]
	uri = 2022-02-09-1644442631-daily-blobless.bundle
	creationToken = 1644442631
	filter = blob:none
[bundle "2022-02-02-1643842568-blobless"]
	uri = /git/git/2022-02-02-1643842568-blobless.bundle
	creationToken = 1643842568
	filter = blob:none

この例では、 `bundle.mode = all` と `bundle.<id>.creationToken` ヒューリスティックを使用しています。また、 `bundle.<id>.filter` オプションを使用して、2つの並列バンドルセットを提示します。1つは完全なクローン用、もう1つはブロブレスの部分クローン用です。

このバンドルリストがURI https://bundles.example.com/git/git/ に存在すると仮定すると、2つのブロブレスバンドルは完全に展開された以下のURIを持ちます。

  • https://bundles.example.com/git/git/2022-02-09-1644442631-daily-blobless.bundle

  • https://bundles.example.com/git/git/2022-02-02-1643842568-blobless.bundle

バンドルURIのアドバタイズ

ユーザーがクローン作成中のリポジトリのバンドルURIを知っている場合、コマンドラインオプションを使用してそのURIを手動で指定できます。ただし、Gitホストは、クローン操作中にバンドルURIをアドバタイズして、この機能を知らないユーザーを支援することができます。

この機能に必要なのは、サーバーが1つ以上のバンドルURIをアドバタイズできることだけです。このアドバタイズは、バンドルURIを検出するための新しいプロトコルv2機能の形式を取ります。

クライアントは、任意のバンドルURIをオプションとして選択するか、探索的チェックによってパフォーマンスが最も良いURIを選択できます。複数のURIを使用する方が、サーバー側のインフラストラクチャを介して地理的に分散された単一のURIを使用するよりも望ましいかどうかは、バンドルプロバイダーが決定します。

バンドルURIを使用したクローン作成

バンドルURIの主な必要性は、クローン作成を高速化することです。 Gitクライアントは、次のフローに従ってバンドルURIと対話します。

  1. ユーザーは、--bundle-uriコマンドラインオプションを使用してバンドルURIを指定するか、クライアントはGitサーバーによってアドバタイズされたバンドルリストを検出します。

  2. バンドルURIからダウンロードされたデータがバンドルの場合、クライアントはバンドルヘッダーを検査して、前提条件となるコミットOIDがクライアントリポジトリに存在することを確認します。不足しているものがある場合、クライアントは他のバンドルがアンバンドルされてOIDが存在するようになるまで、アンバンドルを遅らせます。必要なすべてのOIDが存在する場合、クライアントはrefspecを使用してそのデータをアンバンドルします。デフォルトのrefspecは+refs/heads/*:refs/bundles/*ですが、これは設定可能です。これらのrefは、後でgit fetchネゴシエーションが各バンドルrefをhaveとして通信できるように保存され、Gitプロトコルを介したフェッチのサイズを削減します。このref名前空間からrefをプルーニングできるように、Gitは番号付きの名前空間(refs/bundles/<i>/*など)を導入して、古いバンドルrefを削除できるようにする場合があります。

  3. ファイルがバンドルリストである場合、クライアントはbundle.modeを検査して、リストがall形式かany形式かを確認します。

    1. bundle.mode=allの場合、クライアントはすべてのバンドルURIを考慮します。リストは、クライアントリポジトリの部分クローンフィルターに一致するbundle.<id>.filterオプションに基づいて削減されます。次に、すべてのバンドルURIが要求されます。 bundle.<id>.creationTokenヒューリスティックが提供されている場合、バンドルは作成トークンによって降順にダウンロードされ、バンドルに必要なすべてのOIDが含まれている時点で停止します。その後、バンドルは作成トークンの昇順でアンバンドルできます。クライアントは、バンドルリストがより大きな作成トークンを持つバンドルをアドバタイズしない場合、将来のダウンロードを回避するためのヒューリスティックとして、最新の作成トークンを保存します。

    2. bundle.mode=anyの場合、クライアントは検査するバンドルURIのいずれかを選択できます。クライアントは、これらのURIから選択するためにさまざまな方法を使用できます。クライアントは、最初の選択が結果を返さない場合、別のURIにフォールバックすることもできます。

クローン作成中は、すべてのバンドルが必要になると予想され、bundle.<uri>.creationTokenなどのヒューリスティックを使用して、バンドルを時系列順または並列にダウンロードできます。

特定のバンドルURIがbundle.heuristic値を持つバンドルリストである場合、クライアントはそのURIを選択したバンドルURIとして保存することを選択できます。クライアントは、後のgit fetch呼び出し中にそのURIに直接移動できます。

バンドルURIをダウンロードするとき、クライアントはコンテンツ全体をダウンロードすることをコミットする前に、初期コンテンツを検査することを選択できます。これにより、URIがバンドルリストかバンドルかを判断するのに十分な情報が得られる場合があります。バンドルの場合、クライアントはバンドルヘッダーを検査して、アドバタイズされているすべてのチップがすでにクライアントリポジトリにあり、残りのダウンロードをキャンセルできることを判断できます。

バンドルURIを使用したフェッチ

クライアントが新しいデータをフェッチする場合、オリジンリモートからフェッチする前にバンドルサーバーからフェッチすることを決定できます。これはコマンドラインオプションを介して実行できますが、クローン作成中に指定されたものなどの設定値を使用する方が便利です。

フェッチ操作は、バンドルリストからバンドルをダウンロードするのと同じ手順に従います(ただし、ここでは並列ダウンロードは使用したくありません)。シンバンドルのすべての前提条件となるコミットOIDがすでにオブジェクトデータベースにある場合、プロセスは終了すると予想されます。

creationTokenヒューリスティックを使用する場合、クライアントは、作成トークンが保存されている作成トークンよりも大きくない場合、バンドルのダウンロードを回避できます。新しいバンドルをフェッチした後、Gitはこのローカル作成トークンを更新します。

バンドルプロバイダーがヒューリスティックを提供しない場合、クライアントはバンドルデータ全体をダウンロードする前に、バンドルチップがすでにクライアントリポジトリに存在する場合に備えて、バンドルヘッダーを検査する必要があります。

エラー状態

GitクライアントがバンドルURIまたはその場所に存在するバンドルリストに従って情報をダウンロードしているときに予期しないものを検出した場合、Gitはそのデータを無視し、バンドルURIが指定されていないかのように続行できます。リモートGitサーバーは、バンドルURIではなく、究極の情報源です。

エラー状態の例を次に示します。

  • クライアントは、指定されたURIのサーバーに接続できないか、回復の機会がなく接続が失われます。

  • クライアントは、400レベルの応答(404 Not Found401 Not Authorizedなど)を受信します。クライアントは、資格情報ヘルパーを使用してURIの資格情報を見つけて提供する必要がありますが、特定の400レベルのエラーの処理に関しては、Gitの他のHTTPプロトコルのセマンティクスと一致させる必要があります。

  • サーバーは、その他の障害応答を報告します。

  • クライアントは、バンドルまたはバンドルリストとして解析できないデータを受信します。

  • バンドルには、期待どおりに一致しないフィルターが含まれています。

  • 前提条件となるコミットOIDがオブジェクトデータベースに存在せず、ダウンロードするバンドルがなくなったため、クライアントはバンドルをアンバンドルできません。

無駄と見なされる可能性がありますが、エラー状態ではない状況もあります。

  • ダウンロードされたバンドルには、クローンまたはフェッチリクエストで要求された情報よりも多くの情報が含まれています。主な例は、ユーザーが--single-branchでクローンを要求したが、すべてのrefs/heads/*参照から到達可能なすべてのコミットを保存するバンドルをダウンロードした場合です。これは最初は無駄かもしれませんが、おそらくこれらのオブジェクトは、クライアントが気にする後のref更新によって到達可能になるでしょう。

  • git fetch中のバンドルダウンロードには、すでにオブジェクトデータベースにあるオブジェクトが含まれています。クライアントは「キャッチアップ」フェッチをリモートサーバーに実行した後、ほとんどの場合バンドルサーバーよりもわずかに先行しているため、フェッチにバンドルを使用している場合、これはおそらく避けられません。この余分な作業は、クライアントがサーバーがバンドルを計算するよりもはるかに頻繁にフェッチする場合、たとえば、クライアントがバックグラウンドメンテナンスで1時間ごとのプリフェッチを使用しているが、サーバーが毎週バンドルを計算している場合に最も無駄になります。このため、サーバーがbundle.heuristic値を通じて明示的に推奨していない限り、クライアントはフェッチにバンドルURIを使用しないでください。

バンドルプロバイダーの構成例

バンドルURI機能は、バンドルプロバイダーがオブジェクトデータを編成したいさまざまな方法に柔軟に対応できるように設計されています。ただし、プロバイダーがそのベースから開始できるように、ここで完全な構成モデルを説明しておくと役立ちます。

この構成例は、GVFSキャッシュサーバー(このドキュメントの最後付近のセクションを参照)で使用されているものの簡略化されたモデルです。GVFSキャッシュサーバーは、Git外部の追加ソフトウェアを使用していますが、非常に大きなリポジトリのクローン作成とフェッチの高速化に役立っています。

バンドルプロバイダーは、複数の地域にサーバーを展開します。各サーバーは独自のバンドルセットを管理します。サーバーは多数のGitリポジトリを追跡できますが、パターンに基づいてそれぞれにバンドルリストを提供します。たとえば、https://<domain>/<org>/<repo>にあるリポジトリをミラーリングする場合、バンドルサーバーはhttps://<server-url>/<domain>/<org>/<repo>でバンドルリストを利用できます。オリジンGitサーバーは、「any」モードでこれらのサーバーをすべてリストできます。

[bundle]
	version = 1
	mode = any
[bundle "eastus"]
	uri = https://eastus.example.com/<domain>/<org>/<repo>
[bundle "europe"]
	uri = https://europe.example.com/<domain>/<org>/<repo>
[bundle "apac"]
	uri = https://apac.example.com/<domain>/<org>/<repo>

この「リストのリスト」は静的であり、バンドルサーバーが追加または削除された場合にのみ変更されます。

各バンドルサーバーは、独自のバンドルセットを管理します。初期バンドルリストには、オリジンサーバーからリポジトリをクローンすることによって受信されたすべてのオブジェクトを含む、単一のバンドルのみが含まれています。リストはcreationTokenヒューリスティックを使用し、creationTokenはサーバーのタイムスタンプに基づいてバンドルに対して作成されます。

バンドルサーバーは、1日1回など、定期的にスケジュールされたバンドルリストの更新を実行します。このタスク中、サーバーはオリジンサーバーから最新のコンテンツをフェッチし、最新のオリジンrefから到達可能であるが、以前に計算されたバンドルには含まれていないオブジェクトを含むバンドルを生成します。 creationTokenが前の最大creationTokenよりも厳密に大きいことに注意して、このバンドルがリストに追加されます。

バンドルリストが大きくなりすぎた場合(たとえば、30個を超えるバンドル)、最も古い「*N*マイナス30」個のバンドルが単一のバンドルに結合されます。このバンドルのcreationTokenは、マージされたバンドルの中で最大のcreationTokenと等しくなります。

ここではバンドルリストの例を示しますが、2つの日次バンドルのみが含まれており、30個の完全なリストではありません。

[bundle]
	version = 1
	mode = all
	heuristic = creationToken
[bundle "2022-02-13-1644770820-daily"]
	uri = https://eastus.example.com/<domain>/<org>/<repo>/2022-02-09-1644770820-daily.bundle
	creationToken = 1644770820
[bundle "2022-02-09-1644442601-daily"]
	uri = https://eastus.example.com/<domain>/<org>/<repo>/2022-02-09-1644442601-daily.bundle
	creationToken = 1644442601
[bundle "2022-02-02-1643842562"]
	uri = https://eastus.example.com/<domain>/<org>/<repo>/2022-02-02-1643842562.bundle
	creationToken = 1643842562

オリジンサーバーで到達不能になったにもかかわらず、オブジェクトデータを永続的に保存および提供することを避けるために、このバンドルマージをより慎重に行うことができます。古いバンドルの絶対的な和集合を取る代わりに、新しいバンドルを見て、必要なコミットがすべてこのマージされたバンドル(または新しいバンドルの別のバンドル)で利用可能であることを確認することによって、バンドルを作成できます。これにより、この期間に新しいコミットで使用されていないオブジェクトデータを「期限切れ」にすることができます。そのデータは、後でプッシュすることによって再導入される可能性があります。

このデータ構成の目的は、主に2つの目標があります。1つ目は、より近いソースから事前に計算されたオブジェクトデータをダウンロードすることにより、リポジトリの初期クローン作成が高速化されることです。2つ目は、特にクライアントが数日間フェッチしていない場合、git fetchコマンドが高速化されることです。ただし、クライアントが30日間フェッチしない場合、バンドルリストの構成により、大量のオブジェクトデータが再ダウンロードされます。

頻繁にフェッチを行うユーザーにとってこの構成をより便利にする1つの方法は、バンドルの作成頻度を高くすることです。たとえば、1時間ごとにバンドルを作成し、1日に1回、それらの「時間別」バンドルを「日別」バンドルにマージすることができます。日別バンドルは、30日後に最も古いバンドルにマージされます。

このリポジトリのクライアントがブロブレスの部分クローンを使用することが想定される場合、`blob:none` フィルターを使用してこのバンドル戦略を繰り返すことをお勧めします。このブロブレスバンドルのリストは、完全なバンドルと同じリストに保持されますが、`bundle.<id>.filter` キーを使用して2つのグループを区別します。非常に大きなリポジトリの場合、バンドルプロバイダーは *ブロブレスバンドルのみ* を提供することを希望する場合があります。

実装計画

この設計ドキュメントは、いくつかのパッチシリーズにわたって上記のすべてのクライアント機能を実装することを目標とした、 aspirational なドキュメントとして単独で提出されています。これらの機能を提出するための潜在的な概要を以下に示します。

  1. `--bundle-uri` オプションを使用して、バンドルURIを `git clone` に統合します。これには、`git clone` の実装として使用するための新しい `git fetch --bundle-uri` モードが含まれます。ここでの初期バージョンは、指定されたURIに単一のバンドルがあることを想定しています。

  2. バンドルURIからバンドルリストを解析する機能を実装し、`bundle.mode` オプションを適切に区別するように `git fetch --bundle-uri` ロジックを更新します。具体的には、設定形式の解析がキーと値のペアのリストをバンドルリストロジックにフィードするように機能を設計します。

  3. Gitサーバーがキーと値のペアを使用してバンドルURIをアドバタイズできるように、`bundle-uri` プロトコルv2コマンドを作成します。バンドルリストロジックへの既存のキーと値の入力に接続します。`git clone` がこれらのバンドルURIを検出し、バンドルデータからクライアントリポジトリをブートストラップできるようにします。(この選択は、設定オプションとコマンドラインオプションを介したオプトインです。)

  4. クライアントが `bundle.heuristic` 設定キーと `bundle.<id>.creationToken` ヒューリスティックを理解できるようにします。`git clone` が `bundle.heuristic` を持つバンドルURIを検出すると、後の `git fetch <remote>` コマンド中にそのバンドルURIをチェックするようにクライアントリポジトリを設定します。

  5. クライアントが `git fetch` 中にバンドルURIを検出し、`bundle.heuristic` が設定されている場合、後でフェッチするためのバンドルURIを設定できるようにします。

  6. `bundle.<id>.creationToken` ヒューリスティックが使用できない場合のデータダウンロードを削減するために、「ヘッダーの検査」ヒューリスティックを実装します。

これらの機能がレビューされると、この計画は更新される可能性があります。また、この機能が成熟し、実際のシナリオで使用されるようになるにつれて、新しい設計が発見され、実装されることも期待しています。

Gitプロトコルには、クライアントリクエストを提供する際に、GitサーバーがパックファイルレスポンスとともにURLのセットをリストできる機能が既にあります。クライアントは、レスポンスを完全に理解するために、それらの場所にあるパックファイルをダウンロードすることが期待されています。

このメカニズムはGerritサーバー(JGitで実装)で使用されており、クローン操作のCPU負荷を軽減し、ユーザーパフォーマンスを向上させるのに効果的です。

このメカニズムの大きな欠点は、オリジンサーバーがそれらのパックファイルに *正確に* 何が含まれているかを知る必要があること、そしてパックファイルはサーバーが応答した後もしばらくの間ユーザーが利用できる必要があることです。オリジンとパックファイルデータ間のこの結合は管理が困難です。

さらに、この実装はフェッチで動作させるのが非常に困難です。

GVFSプロトコル[2]は、Gitの部分クローンが作成される前にGitプロジェクトとは独立して設計されたHTTPエンドポイントのセットです。このプロトコルの1つの機能は、中央サーバーに過負荷をかけることなくGitデータを転送するために、ビルドマシンまたは開発オフィスと同じ場所に配置できる「キャッシュサーバー」の概念です。

VFS for Gitが有名になったエンドポイントは、`GET /gvfs/objects/{oid}` エンドポイントであり、オンデマンドでオブジェクトをダウンロードできます。これは、その製品のファイルシステム仮想化の重要な部分です。

ただし、より微妙なニーズは、`GET /gvfs/prefetch?lastPackTimestamp=<t>` エンドポイントです。オプションのタイムスタンプが指定されると、キャッシュサーバーは、それらの時間間隔で導入されたコミットとツリーを含む、事前に計算されたパックファイルのリストで応答します。

キャッシュサーバーは、次の戦略を使用してこれらの「プリフェッチ」パックファイルを計算します。

  1. 1時間ごとに、指定されたタイムスタンプを持つ「時間別」パックが生成されます。

  2. 毎晩、前の24個の時間別パックが「日別」パックにロールアップされます。

  3. 毎晩、30日以上経過したすべてのプリフェッチパックが1つのパックにロールアップされます。

ユーザーがキャッシュサーバーを使用してリポジトリに対して `gvfs clone` または `scalar clone` を実行すると、クライアントはすべてのプリフェッチパックファイルをリクエストします。これは最大で `24 + 30 + 1` 個のパックファイルであり、コミットとツリーのみをダウンロードします。次に、クライアントはオリジンサーバーに参照をリクエストし、その先端の参照をチェックアウトしようとします。(そのコミットがプリフェッチパックファイルにまだない場合に備えて、指定されたコミットから到達可能なすべてのツリーを取得するのに役立つ追加のエンドポイントがあります。)

`git fetch` 中に、フックは以前にダウンロードしたプリフェッチパックファイルの最新のタイムスタンプを使用してプリフェッチエンドポイントをリクエストします。後のタイムスタンプを持つパックファイルのリストのみがダウンロードされます。ほとんどのユーザーは1時間ごとにフェッチするため、最大で1つの時間別プリフェッチパックを取得します。マシンがオフになっているか、30日以上フェッチしていないユーザーは、すべてのプリフェッチパックファイルを再ダウンロードする可能性があります。これはまれです。

クライアントは常に参照アドバタイズメントのためにオリジンサーバーに接続するため、参照はプリフェッチされたパックデータよりも頻繁に「先行」することに注意することが重要です。不足しているオブジェクトは、`git checkout` や `git log` などのコマンドで必要な場合に、`GET gvfs/objects/{oid}` リクエストを使用してオンデマンドでダウンロードされます。一部のGitの最適化では、これらのオンデマンドダウンロードが過剰になる原因となるチェックが無効になっています。

scroll-to-top