セットアップと設定
プロジェクトの取得と作成
基本的なスナップショット作成
ブランチとマージ
プロジェクトの共有と更新
検査と比較
パッチ適用
デバッグ
メール
外部システム
サーバー管理
ガイド
- gitattributes
- コマンドラインインターフェースの慣例
- 日常のGit
- よくある質問 (FAQ)
- 用語集
- フック
- gitignore
- gitmodules
- リビジョン
- サブモジュール
- チュートリアル
- ワークフロー
- すべてのガイド...
管理
プラミングコマンド
- 2.40.1 → 2.49.0 変更なし
-
2.40.0
2023-03-12
- 2.38.3 → 2.39.5 変更なし
-
2.38.2
2022-12-11
- 2.38.1 変更なし
-
2.38.0
2022-10-02
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 を必要とするか、またはいずれか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
のいずれかです。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 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=all
と bundle.<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 と対話します
-
ユーザーは
--bundle-uri
コマンドラインオプションでバンドル URI を指定するか、クライアントが Git サーバーによってアドバタイズされたバンドルリストを検出します。 -
バンドル URI からダウンロードされたデータがバンドルである場合、クライアントはバンドルヘッダーを検査し、前提条件となるコミット OID がクライアントリポジトリに存在することを確認します。一部が欠落している場合、クライアントは他のバンドルがアンバンドルされてそれらの OID が存在するようになるまでアンバンドルを遅らせます。必要なすべての OID が存在する場合、クライアントは refspec を使用してそのデータをアンバンドルします。デフォルトの refspec は
+refs/heads/*:refs/bundles/*
ですが、これは設定可能です。これらの参照は、後のgit fetch
ネゴシエーションで各バンドルされた参照をhave
として通信できるように保存され、Git プロトコルを介したフェッチのサイズを削減します。この参照名前空間から参照をプルーニングできるように、Git は古いバンドル参照を削除できるように番号付きの名前空間(refs/bundles/<i>/*
など)を導入する可能性があります。 -
ファイルがバンドルリストである場合、クライアントは
bundle.mode
を検査し、リストがall
形式かany
形式かを確認します。-
bundle.mode=all
の場合、クライアントはすべてのバンドル URI を考慮します。リストは、クライアントリポジトリのパーシャルクローンフィルターに一致するbundle.<id>.filter
オプションに基づいて絞り込まれます。その後、すべてのバンドル URI が要求されます。bundle.<id>.creationToken
ヒューリスティックが提供されている場合、バンドルは作成トークンに基づいて降順でダウンロードされ、バンドルにすべての必要な OID が含まれているときに停止します。その後、バンドルは作成トークンの昇順でアンバンドルできます。バンドルリストがより大きな作成トークンを持つバンドルをアドバタイズしない場合、クライアントは将来のダウンロードを回避するためのヒューリスティックとして最新の作成トークンを保存します。 -
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日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
オリジンサーバーで到達不能になってもオブジェクトデータを永久に保存および提供するのを避けるために、このバンドルマージはより慎重に行うことができます。古いバンドルの絶対的な結合を行う代わりに、新しいバンドルを見て、必要なコミットがすべてこの結合されたバンドル(または新しいバンドルの別のもの)で利用可能であることを確認することによってバンドルを作成できます。これにより、この期間に新しいコミットによって使用されていないオブジェクトデータを「期限切れ」にすることができます。そのデータは、後のプッシュによって再導入される可能性があります。
このデータ構成の意図には2つの主要な目標があります。第一に、リポジトリの初期クローンは、より近いソースから事前に計算されたオブジェクトデータをダウンロードすることで高速化されます。第二に、git fetch
コマンドは、特にクライアントが数日間フェッチしていない場合に高速化されます。しかし、クライアントが30日間フェッチしない場合、バンドルリストの構成により大量のオブジェクトデータが再ダウンロードされることになります。
頻繁にフェッチするユーザーにとってこの構成をより有用にする1つの方法は、バンドルの作成頻度を増やすことです。たとえば、バンドルを毎時作成し、その後1日1回それらの「時間ごと」のバンドルを「日次」バンドルにマージすることができます。日次バンドルは30日後に最も古いバンドルにマージされます。
このリポジトリのクライアントがブロブなしパーシャルクローンを使用する予定がある場合、このバンドル戦略を blob:none
フィルターで繰り返すことが推奨されます。このブロブなしバンドルのリストは、完全なバンドルと同じリストに留まりますが、2つのグループを分離するために bundle.<id>.filter
キーを使用します。非常に大規模なリポジトリの場合、バンドルプロバイダーはブロブなしバンドルをのみ提供したいと考えるかもしれません。
実装計画
この設計ドキュメントは、言及されたすべてのクライアント機能をいくつかのパッチシリーズにわたって実装することを目標とした、将来的なドキュメントとして単独で提出されています。これらの機能を提出するための潜在的なアウトラインは以下の通りです
-
git clone
に--bundle-uri
オプションでバンドル URI を統合します。これには、git clone
の実装として使用するための新しいgit fetch --bundle-uri
モードが含まれます。ここでの最初のバージョンでは、指定された URI に単一のバンドルがあることを想定します。 -
バンドル URI からバンドルリストを解析する機能を実装し、
git fetch --bundle-uri
ロジックを更新してbundle.mode
オプションを適切に区別できるようにします。具体的には、設定形式の解析がキーと値のペアのリストをバンドルリストロジックに供給するように機能を設計します。 -
Git サーバーがキーと値のペアを使用してバンドル URI をアドバタイズできるように、
bundle-uri
プロトコル v2 コマンドを作成します。既存のキーと値の入力をバンドルリストロジックに接続します。git clone
がこれらのバンドル URI を検出し、バンドルデータからクライアントリポジトリをブートストラップできるようにします。(この選択は、設定オプションおよびコマンドラインオプションを介したオプトインです。) -
クライアントが
bundle.heuristic
設定キーとbundle.<id>.creationToken
ヒューリスティックを理解できるようにします。git clone
がbundle.heuristic
を持つバンドル URI を検出すると、後のgit fetch <remote>
コマンド中にそのバンドル URI をチェックするようにクライアントリポジトリを設定します。 -
git fetch
中にクライアントがバンドル URI を検出できるようにし、bundle.heuristic
が設定されている場合は、その後のフェッチのためにバンドル URI を設定できるようにします。 -
bundle.<id>.creationToken
ヒューリスティックが利用できない場合にデータダウンロードを減らすための「ヘッダー検査」ヒューリスティックを実装します。
これらの機能がレビューされるにつれて、この計画は更新される可能性があります。また、この機能が成熟し、実際のシナリオで使用されるようになるにつれて、新しい設計が発見され、実装されることも期待しています。
関連作業: パックファイル URI
Git プロトコルにはすでに、クライアント要求に応答する際に、Git サーバーがパックファイル応答とともに一連の URL をリストできる機能があります。クライアントはその後、応答を完全に理解するために、それらの場所にあるパックファイルをダウンロードすることが期待されます。
このメカニズムは Gerrit サーバー(JGit で実装)によって使用されており、CPU 負荷の軽減とクローンのユーザーパフォーマンス向上に効果的でした。
このメカニズムの大きな欠点は、オリジンサーバーがそれらのパックファイルに何が含まれているかを正確に知っている必要があり、サーバーが応答した後もパックファイルが一定期間ユーザーに利用可能である必要があることです。オリジンとパックファイルデータのこの結合は管理が困難です。
さらに、この実装をフェッチで動作させることは非常に困難です。
関連作業: GVFS キャッシュサーバー
GVFS プロトコル [2] は、Git のパーシャルクローンが作成される前に Git プロジェクトとは独立して設計された一連の HTTP エンドポイントです。このプロトコルの1つの機能は、「キャッシュサーバー」という概念です。これはビルドマシンや開発者オフィスに併置でき、中央サーバーを過負荷にすることなく Git データを転送できます。
VFS for Git が有名にしたエンドポイントは、GET /gvfs/objects/{oid}
エンドポイントであり、これによりオブジェクトをオンデマンドでダウンロードできます。これは、その製品のファイルシステム仮想化の重要な要素です。
しかし、より微妙なニーズは、GET /gvfs/prefetch?lastPackTimestamp=<t>
エンドポイントです。オプションのタイムスタンプが与えられると、キャッシュサーバーは、その時間間隔で導入されたコミットとツリーを含む、事前に計算されたパックファイルのリストで応答します。
キャッシュサーバーは、以下の戦略を使用してこれらの「プリフェッチ」パックファイルを計算します
-
毎時、「時間ごと」のパックが特定のタイムスタンプで生成されます。
-
毎晩、前の24時間のパックが「日次」パックにロールアップされます。
-
毎晩、30日以上前のすべてのプリフェッチパックが1つのパックにロールアップされます。
ユーザーがキャッシュサーバーを持つリポジトリに対して gvfs clone
または scalar clone
を実行すると、クライアントはすべてのプリフェッチパックファイル(最大でコミットとツリーのみをダウンロードする 24 + 30 + 1
個のパックファイル)を要求します。その後、クライアントはオリジンサーバーに参照を要求し、その先端参照をチェックアウトしようとします。(そのコミットがすでにプリフェッチパックファイルになかった場合に、特定のコミットから到達可能なすべてのツリーを取得するのに役立つ追加のエンドポイントがあります。)
git fetch
の際、フックは以前にダウンロードされたプリフェッチパックファイルからの最新のタイムスタンプを使用してプリフェッチエンドポイントを要求します。より新しいタイムスタンプを持つパックファイルのリストのみがダウンロードされます。ほとんどのユーザーは毎時フェッチするため、最大で1つの毎時プリフェッチパックを取得します。マシンがオフになっていた、または30日以上フェッチしていなかったユーザーは、すべてのプリフェッチパックファイルを再ダウンロードする可能性があります。これは稀なケースです。
クライアントが常に参照アドバタイズのためにオリジンサーバーに接続するため、参照はプリフェッチされたパックデータよりも頻繁に「先行」していることに注意することが重要です。不足しているオブジェクトは、git checkout
や git log
などのコマンドで必要になったときに、GET gvfs/objects/{oid}
リクエストを使用してオンデマンドでダウンロードされます。一部の Git の最適化は、これらのオンデマンドダウンロードが過度に積極的になる原因となるチェックを無効にします。
関連項目
[1] https://lore.kernel.org/git/RFC-cover-00.13-0000000000-20210805T150534Z-avarab@gmail.com/ バンドル URI 機能に関する以前の RFC。