日本語 ▾ トピック ▾ 最新バージョン ▾ bundle-uri は 2.50.0 で最終更新されました

Gitバンドルは、パックファイルと、一連の参照と(空の場合もある)一連の必要なコミットを含むいくつかの追加のメタデータを格納するファイルです。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を必要とするか、_いずれか_のバンドルURIで十分であるかを指定できます。これにより、バンドルプロバイダーは、異なる地域で異なるURIを使用できます。

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

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

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

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

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

サーバー要件

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

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

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

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

バンドルリスト

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

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

bundle.version

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

bundle.mode

(必須)この値には、allanyの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.modeanyの場合にのみ有効です。

以下は、Git config形式を使用したバンドルリストの例です。

[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=allbundle.<id>.creationTokenヒューリスティックを使用しています。また、bundle.<id>.filterオプションを使用して、2つの並行するバンドルセット(フルクローン用とブロブレス部分クローン用)を提示しています。

このバンドルリストが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/*:refs/bundles/*です。これらの参照は保存され、後のgit fetchネゴシエーションが各バンドルされた参照をhaveとして通信できるようにし、Gitプロトコルを介したフェッチのサイズを減らします。このref名前空間から参照をプルーニングできるように、Gitは番号付き名前空間(refs/bundles/<i>/*など)を導入して、古いバンドル参照を削除できるようにする場合があります。

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

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

    2. もしbundle.mode=anyの場合、クライアントはバンドルURIのいずれか1つを選択して検査できます。クライアントはこれらの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 Foundまたは401 Not Authorized)。クライアントは、資格情報ヘルパーを使用してURIの資格情報を見つけて提供する必要がありますが、特定の400レベルのエラーの処理に関して、Gitの他のHTTPプロトコルのセマンティクスに一致させる必要があります。

  • サーバーがその他の障害応答を報告する。

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

  • バンドルに、期待に合わないフィルターが含まれている。

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

無駄に見える状況もありますが、エラー条件ではありません。

  • ダウンロードされたバンドルに、クローンまたはフェッチリクエストで要求された以上の情報が含まれている。主な例として、ユーザーが--single-branchでクローンをリクエストしたが、すべてのrefs/heads/*参照から到達可能なすべてのコミットを格納するバンドルをダウンロードした場合が挙げられます。これは最初は無駄かもしれませんが、クライアントが関心を持つ後の参照更新によってこれらのオブジェクトが到達可能になる可能性があります。

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

バンドルプロバイダー組織の例

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

この組織例は、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回など、バンドルリストの定期的な更新を実行します。このタスク中に、サーバーはオリジンサーバーから最新のコンテンツをフェッチし、最新のオリジンリファレンスから到達可能であるが、以前に計算されたバンドルに含まれていないオブジェクトを含むバンドルを生成します。このバンドルはリストに追加され、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

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

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

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

このリポジトリのクライアントがブロブレス部分クローンを使用することを想定している場合、このバンドル戦略はblob:noneフィルターで繰り返されることを推奨します。ブロブレスバンドルのリストはフルバンドルと同じリストにありますが、bundle.<id>.filterキーを使用して2つのグループを分離します。非常に大規模なリポジトリの場合、バンドルプロバイダーは_ブロブレスバンドルのみ_を提供したい場合があります。

実装計画

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

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

  2. バンドルURIからバンドルリストを解析する機能を実装し、git fetch --bundle-uriロジックを更新して、bundle.modeオプションを適切に区別できるようにします。特に、構成形式の解析がキーと値のペアのリストをバンドルリストロジックに供給するように機能を設計します。

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

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

  5. bundle.heuristicが設定されている場合、クライアントがgit fetch中にバンドルURIを検出し、その後のフェッチのためにバンドル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 checkoutgit logなどのコマンドで必要になったときに、GET gvfs/objects/{oid}リクエストを使用してオンデマンドでダウンロードされます。一部のGit最適化は、これらのオンデマンドダウンロードが積極的になりすぎる原因となるチェックを無効にします。

scroll-to-top