このドキュメントは、Gitのワイヤープロトコルのバージョン2の仕様を示しています。プロトコルv2は、以下の方法でv1を改善します:

  • 複数のサービス名の代わりに、単一のサービスで複数のコマンドがサポートされます

  • 機能(capability)がプロトコルの独自のセクションに移動され、NULバイトの後ろに隠されたり、pkt行のサイズによって制限されたりすることがないため、簡単に拡張できます。

  • NULバイトの後ろに隠されている他の情報を分離します(たとえば、機能(capability)としてのエージェント文字列とsymrefsは ls-refs を使用して要求できます)

  • 明示的に要求されない限り、 reference advertisement は省略されます

  • 一部のrefを明示的に要求する ls-refs コマンド

  • http と stateless-rpc を念頭に置いて設計されています。明確なフラッシュセマンティクス(flush semantics)を使用すると、httpリモートヘルパーは単にプロキシとして機能できます

プロトコルv2では、通信はコマンド指向です。サーバーに最初に接続するときに、機能のリストが広告されます。これらの機能の一部は、クライアントが実行を要求できるコマンドになります。コマンドが完了すると、クライアントは接続を再利用して、他のコマンドの実行を要求できます。

Packet-Line Framing

すべての通信は、v1と同様に、パケットラインフレーミングを使用して行われます。 詳細については、 Documentation/technical/pack-protocol.txtDocumentation/technical/protocol-common.txt を参照してください。

プロトコルv2では、これらの特別なパケットの意味は以下のとおりです:

  • 0000 フラッシュパケット (flush-pkt) - メッセージの終わりを示します

  • 0001 区切りパケット (delim-pkt) - メッセージのセクションを区切ります

  • 0002 応答終了パケット (response-end-pkt) - ステートレス接続の応答の終了を示します

Initial Client Request

一般に、クライアントは、使用されているトランスポートのそれぞれのサイドチャネルを介して version=2 を送信することにより、プロトコルv2を話すように要求できます。これにより、必然的に GIT_PROTOCOL が定されます。詳細については pack-protocol.txthttp-protocol.txt と、 git.txtGIT_PROTOCOL 定義を参照してください。すべての場合において、サーバーからの応答は機能広告(capability advertisement)です。

Git Transport

git:// 輸送を使用する場合、追加のパラメーターとして "version=2" を送信することにより、プロトコルv2の使用を要求できます:

003egit-upload-pack /project.git\0host=myserver.com\0\0version=2\0

SSH and File Transport

ssh:// 輸送 または file:// 輸送 のどちらかを使用する場合、GIT_PROTOCOL環境変数を明示的に設定して「version=2」を含める必要があります。この環境変数が渡されるようにサーバーを構成する必要がある場合があります。

HTTP Transport

http:// 輸送 または https:// 輸送 を使用する場合、クライアントは「http-protocol.txt」で説明されているように「smart」なinfo/refsリクエストを作成し、 Git-Protocol ヘッダー内で「version=2」を指定してv2を使用するように要求します。

C: GET $GIT_URL/info/refs?service=git-upload-pack HTTP/1.0
C: Git-Protocol: version=2

v2サーバーは以下のように応答します:

S: 200 OK
S: <Some headers>
S: ...
S:
S: 000eversion 2\n
S: <capability-advertisement>

その後の要求は、サービス $GIT_URL/git-upload-pack に対して直接行われます。(これはgit-receive-packでも同じように機能します)。

--http-backend-info-refs オプションを使用して git-upload-pack(1) を実行します。

サーバーは、 GIT_PROTOCOL 変数を介してこのヘッダーの内容を渡すように構成する必要がある場合があります。 git-http-backend.txt の説明を参照してください。

Capability Advertisement

(クライアントからの要求に基づいて)プロトコルバージョン2を使用して通信することを決定したサーバーは、初期応答でバージョン文字列を送信し、続いてその機能を広告することによってクライアントに通知します。各機能は、オプションの値を持つキーです。クライアントは、不明なキーをすべて無視する必要があります。未知の値の意味は、各キーの定義に任されています。一部の機能では、クライアントによる実行を要求できるコマンドについて説明します。

capability-advertisement = protocol-version
                           capability-list
                           flush-pkt
protocol-version = PKT-LINE("version 2" LF)
capability-list = *capability
capability = PKT-LINE(key[=value] LF)
key = 1*(ALPHA | DIGIT | "-_")
value = 1*(ALPHA | DIGIT | " -_.,?\/{}[]()<>!@#$%^&*+=:;")

Command Request

機能広告を受信した後、クライアントは、特定の機能または引数を使用して、必要なコマンドを選択する要求を発行できます。その次に、クライアントがコマンド固有のパラメータまたはクエリを提供できるオプションのセクションがあります。 一度に要求できるコマンドは1つだけです。

request = empty-request | command-request
empty-request = flush-pkt
command-request = command
                  capability-list
                  [command-args]
                  flush-pkt
command = PKT-LINE("command=" key LF)
command-args = delim-pkt
               *command-specific-arg
command-specific-argsは、個々のコマンドによって定義される
パケットラインフレームの引数です。

次に、サーバーは、クライアントの要求が、広告された有効な機能だけでなく、有効なコマンドで構成されていることを確認します。リクエストが有効な場合、サーバーはコマンドを実行します。 サーバーは、応答を発行する前に、クライアントの要求全体を受信するまで待機する必要があります。応答の形式は実行中のコマンドによって決まりますが、すべての場合で、flush-pktは応答の終了を示します。

コマンドが終了し、クライアントがサーバーからの応答全体を受信すると、クライアントは別のコマンドの実行を要求するか、接続を終了することができます。 クライアントは、オプションで、flush-pktのみで構成される空の要求を送信して、これ以上要求が行われないことを示すことができます。

Capabilities

機能には異なる2つのタイプがあります。情報を伝達したり要求の動作を変更したりするために使用できる通常の機能と、クライアントが実行したいコアアクション(フェッチ、プッシュなど)であるコマンドです。

プロトコルバージョン2は、デフォルトではステートレスです。 つまり、クライアントがサーバーで状態を維持する必要があることを指示する機能を要求しない限り、すべてのコマンドは1ラウンドだけ持続し、サーバー側の観点からステートレスである必要があります。クライアントは、正しく機能するためにサーバー側に状態管理を要求してはいけません(MUST NOT)。これにより、サーバー側では状態管理について心配することなく、単純なラウンドロビン負荷分散が可能になります。

agent

サーバーは、値 X (agent=X 形式)を使用して agent 機能を広告ズし、サーバーがバージョン X を実行していることをクライアントに通知できます。クライアントは、サーバーへの要求に値 Y (agent=Y 形式)を持つ agent 機能を含めることにより、オプションで独自のエージェント文字列を送信できます(ただし、サーバーがagent機能を広告しなかった場合は、クライアントから送信してはいけません(MUST NOT))。X および Y 文字列には、スペースを除く任意の印刷可能なASCII文字(つまり、バイト範囲32 < x <127)を含めることができ、通常は「パッケージ/バージョン」(例: 「git/1.8.3.1」形式です)。エージェント文字列は、統計およびデバッグの目的で純粋に情報を提供するものであり、特定の機能の有無をプログラムで想定するために使用してはいけません(MUST NOT)。

ls-refs

ls-refs は、v2で参照広告を要求するために使用されるコマンドです。現在の参照広告とは異なり、ls-refsは、サーバーから送信される参照を制限するために使用できる引数を取ります。

基本コマンドでサポートされていない追加の機能は、機能広告のコマンドの値として、スペースで区切られた機能のリストの形式で広告されます: "<command>=<feature 1> <feature 2>"

ls-refsは以下の引数を取ります:

symrefs

それが指すオブジェクトに加えて、シンボリックrefを表示するときに、それが指す基になるrefを表示します。

peel

剥いたタグ(peeled tags)を表示します。

ref-prefix <prefix>

指定すると、指定されたプレフィックスの1つと一致するプレフィックスを持つ参照のみが表示されます。

「unborn」機能が広告される場合、以下の引数をクライアントの要求に含めることができます。

unborn

サーバーは、 unborn HEAD symref-target:<target> の形式で、unbornブランチを指すsymrefであっても、HEADに関する情報を送信します。

ls-refsの出力は以下のとおりです:

output = *ref
         flush-pkt
obj-id-or-unborn = (obj-id | "unborn")
ref = PKT-LINE(obj-id-or-unborn SP refname *(SP ref-attribute) LF)
ref-attribute = (symref | peeled)
symref = "symref-target:" symref-target
peeled = "peeled:" obj-id

fetch

fetch は、v2でパックファイルをフェッチするために使用されるコマンドです。 これは、v1 fetch の修正バージョンと見なすことができ、(ls-refs コマンドがその役割を果たしているため、)ref-advertisementが削除され、メッセージ形式が調整されて冗長性が排除され、将来の拡張機能を簡単に追加できるようになっています。

基本コマンドでサポートされていない追加の機能は、機能広告のコマンドの値として、スペースで区切られた機能のリストの形式で広告されます: "<command>=<feature 1> <feature 2>"

fetch リクエストは、以下の引数を取ることができます:

want <oid>

クライアントが取得したいオブジェクトをサーバーに提示します。欲しいものは何でもかまいません。広告されているオブジェクトに限定されません。

have <oid>

クライアントがローカルに持っているオブジェクトをサーバーに提示します。 これにより、サーバーは、クライアントが必要とするオブジェクトのみを含むパックファイルを作成できます。 複数の「have」行を指定できます。

done

ネゴシエーションを終了する必要があること(またはクローンを実行する場合は開始しないこと)、およびサーバーが要求で提供された情報を使用してパックファイルを作成する必要があることをサーバーに提示します。

thin-pack

シンパック(thin pack)の送信を要求します。これは、パック内に含まれていない(ただし、受信側に存在することがわかっている)ベースオブジェクトを参照するデルタを含むパックです。これにより、ネットワークトラフィックを大幅に削減できますが、受信側は、シンパックに不足しているベースを追加して、これらのパックを「厚く」(thicken)する方法を知っている必要があります。

no-progress

パックファイル転送中にサイドバンドチャネル2で通常送信される進行状況情報を送信しないように要求します。 ただし、サイドバンドチャネル3は引き続きエラー応答に使用されます。

include-tag

注釈付きタグ(annotated tags)が指すオブジェクトが送信されている場合は、注釈付きタグ(annotated tags)を送信するように要求します。

ofs-delta

クライアントが PACKv2を理解していることを提示します。デルタは、OIDではなくパック内の位置によってベースを参照しています。 つまり、パックファイル内の OBJ_OFS_DELTA (別名タイプ 6)を読み取ることができます。

「shallow」機能が広告される場合、以下で説明するように、以下の引数をクライアント要求に含めることができ、サーバーの応答に「shallow-info」セクションを追加する可能性があります。

shallow <oid>

クライアントは、サーバーがクライアントの履歴の制限を認識できるように、そのようなオブジェクトごとに「shallow <oid>」行を指定することにより、shallowコピーしかない(つまり、そのコミットの親がないことを意味する、)すべてのコミットをサーバーに通知する必要があります。 これは、クライアントがそのようなコミットから到達可能なすべてのオブジェクトを持っていない可能性があることをサーバーが認識できるようにするためです。

deepen <depth>

フェッチ/クローンを浅くし(shallow)、リモート側に対してコミットの深さが<depth>であることを要求します。

deepen-relative

「deepen」コマンドのセマンティクスを変更して、要求された深さが、要求されたコミットではなく、クライアントの現在のshallow境界に関連していることを示すように要求します。

deepen-since <timestamp>

shallow クローン/フェッチ を深さではなく特定の日付時刻でカットするように要求します。 内部的には、「git rev-list --max-age=<timestamp>」を実行するのと同じです。 「deepen」との併用はできません。

deepen-not <rev>

shallow クローン/フェッチを、深さではなく、 <rev> で指定された特定のリビジョンでカットするように要求します。 内部的には、「git rev-list --not <rev>」を実行するのと同じです。 「deepen」では使用できませんが、「deepen-since」では使用できます。

filter 機能が広告される場合、以下の引数をクライアントの要求に含めることができます:

filter <filter-spec>

いくつかのフィルタリング手法のいずれかを使用して、パックファイルのさまざまなオブジェクトを省略するように要求します。これらは、部分クローン(partial clone)および部分フェッチ(partial fetch)操作での使用を目的としています。 可能な「filter-spec」値については、rev-list を参照してください。他のプロセスと通信する場合、送信者はスケーリングされた整数(「1k」など)を完全に拡張された形式(「1024」など)に変換して、新発想のスケーリングサフィックスを理解できない古い受信者との相互運用性を支援する必要があります。しかしながら、受信者は次のサフィックスを受け入れる必要があります:「k」、「m」、「g」で、それぞれ、1024、1048576、1073741824 を現します。

「ref-in-want」機能が広告される場合、以下で説明するように、以下の引数をクライアントの要求に含めることができ、サーバーの応答に「wanted-refs」セクションを追加する可能性があります。

want-ref <ref>

クライアントが特定のrefを取得することをサーバーに提示します。ここで、 <ref> はサーバー上のrefのフルネームです。

sideband-all 機能が広告される場合、以下の引数をクライアントの要求に含めることができます:

sideband-all

packfileセクションだけでなく、応答全体を多重化して送信するようにサーバーに指示します。(packfileセクションだけでなく、)応答内のすべての非フラッシュ(non-flush)および non-delim PKT-LINEは、そのサイドバンド(1または2または3)を示すバイトで始まります。サーバーは、キープアライブパケットとして「0005\2」(ペイロードのないサイドバンド2のPKT-LINE)を送信する場合があります。

「packfile-uris」機能が広告される場合、以下で説明するように、以下の引数をクライアントの要求に含めることができ、サーバーの応答に「packfile-uris」セクションを追加する可能性があります。

packfile-uris <comma-separated list of protocols>

クライアントが、送信されたパックファイル内のオブジェクトの代わりに、指定されたプロトコルのいずれかのURIを受信する用意があることをサーバーに提示します。 接続チェックを実行する前に、クライアントは指定されたすべてのURIからダウンロードする必要があります。 現在、サポートされているプロトコルは「http」と「https」です。

「wait-for-done」機能が広告される場合、以下の引数をクライアントの要求に含めることができます。

wait-for-done

サーバは決して "ready" を送らず、クライアントが "done" と言うまで待ってからパックファイルを送信するように指示します。

fetch の応答は、区切り文字パケット(0001)で区切られたいくつかのセクションに分割され、各セクションはセクションヘッダーで始まります。ほとんどのセクションは、パックファイルが送信されたときにのみ送信されます。

output = acknowledgements flush-pkt |
         [acknowledgments delim-pkt] [shallow-info delim-pkt]
         [wanted-refs delim-pkt] [packfile-uris delim-pkt]
         packfile flush-pkt
acknowledgments = PKT-LINE("acknowledgments" LF)
                  (nak | *ack)
                  (ready)
ready = PKT-LINE("ready" LF)
nak = PKT-LINE("NAK" LF)
ack = PKT-LINE("ACK" SP obj-id LF)
shallow-info = PKT-LINE("shallow-info" LF)
               *PKT-LINE((shallow | unshallow) LF)
shallow = "shallow" SP obj-id
unshallow = "unshallow" SP obj-id
wanted-refs = PKT-LINE("wanted-refs" LF)
              *PKT-LINE(wanted-ref LF)
wanted-ref = obj-id SP refname
packfile-uris = PKT-LINE("packfile-uris" LF) *packfile-uri
packfile-uri = PKT-LINE(40*(HEXDIGIT) SP *%x20-ff LF)
packfile = PKT-LINE("packfile" LF)
           *PKT-LINE(%x01-03 *%x00-ff)
acknowledgments section
  • クライアントが「done」行を送信してネゴシエーションが終了したと判断した場合(したがって、サーバーにパックファイルを送信する必要があります)、サーバーの応答からacknowledgmentsセクションを省略しなければなりません(MUST)。

  • 常にセクションヘッダー「acknowledgements」で始まります

  • have行として送信されたオブジェクトIDがどれも共通していない場合、サーバーは「NAK」で応答します。

  • サーバーは、共通のhave行として送信されたすべてのオブジェクトIDに対して「ACK obj-id」で応答します。

  • 応答に「ACK」行と「NAK」行の両方を含めることはできません。

  • サーバーは、サーバーが許容可能な共通ベースを検出し、packfile(同じ応答のpackfileセクションにあります)を作成して、送信する準備ができていることを示す「ready」行で応答します。

  • サーバーが適切な切断点(cut point)を見つけて「ready」行を送信することを決定した場合、サーバーは(最適化として)応答中に送信した「ACK」行を省略することを決定できます。これは、サーバーがクライアントに送信する予定のオブジェクトをすでに決定しており、それ以上のネゴシエーションが必要ないためです。

shallow-info section
  • クライアントが shallow フェッチ/クローン を要求した場合、shallowクライアントがフェッチを要求するか、サーバーがshallowの場合、サーバーの応答に shallow-info セクションが含まれる場合があります。(上記の条件のいずれかにより、サーバーがクライアントにshallow 境界(shallow boundaries)を通知する必要がある場合、または既存の浅い境界をクライアントと調整する必要がある場合は、 shallow-info セクションが含まれます。

  • 常にセクションヘッダー「shallow-info」で始まります

  • 正数の深さが要求された場合、サーバーは指定の深さよりも深くないコミットのセットを計算します。

  • サーバーは、続くパックファイルで親が送信されないコミットごとに「shallow obj-id」行を送信します。

  • サーバーは、クライアントがshallowを指示したコミットごとに「unshallow obj-id」行を送信しますが、(その親が次のパックファイルで送信されるため、)フェッチの結果としてはshallowにはなりません。

  • サーバーは、クライアントが要求の一部としてshallowを指示していないものに対して、「unshallow」行を送信しては「いけません」。

wanted-refs section
  • このセクションは、クライアントが「want-ref」行を使用してrefを要求し、packfileセクションも応答に含まれている場合にのみ含まれます。

  • 常にセクションヘッダー「wanted-refs」で始まります。

  • サーバーは、「want-ref」行を使用して要求された参照ごとに、参照リスト("<oid> <refname>")を送信します。

  • サーバーは、「want-ref」行を使用して要求されなかった参照を送信しては「いけません」。

packfile-uris section
  • このセクションは、クライアントが「packfile-uris」を送信し、サーバーに送信するそのようなURIが少なくとも1つある場合にのみ含まれます。

  • 常にセクションヘッダー「packfile-uris」で始まります。

  • サーバーが送信するURIごとに、パックの内容のハッシュ(git index-packによって出力される)と、それに続くURIを送信します。

  • ハッシュの長さは40文字です。 Gitが新しいハッシュアルゴリズムにアップグレードするとき、これを更新する必要があるかもしれません。 (「pack\t」または「keep\t」の後に出力されるインデックスパックと一致する必要があります)。

packfile section
  • このセクションは、クライアントがリクエストで「want」行を送信し、「done」を送信してこれ以上ネゴシエーションを行わないように要求した場合、または、サーバーがパックファイルを生成するのに十分なカットポイントを見つけたと判断した場合、のいずれかにのみ含まれます。

  • 常にセクションヘッダー「packfile」で始まります

  • パックファイルの送信は、セクションヘッダーの直後に開始されます

  • パックファイルのデータ転送は、プロトコルバージョン1の「side-band-64k」機能と同じセマンティクスを使用して、常に多重化されます。つまり、packfileデータストリーム中の各パケットは、先頭の4バイトの pkt-line長(通常はpkt-line形式)、1バイトのストリームコード、実際のデータで構成されます。

    ストリームコードは以下のいずれかになります:
          1 - パックデータ
          2 - 進行状況メッセージ
          3 - ストリームが中止(abort)される直前の致命的なエラーメッセージ

server-option

広告されている場合は、サーバー固有のオプションをいくつでもリクエストに含めることができることを示します。これは、リクエストの機能リストセクションで「server-option=<option>」機能行として各オプションを送信することによって行われます。

提供されるオプションには、NULまたはLF文字を含めることはできません。

object-format

サーバーは、値 X (object-format=X 形式)を使用して object-format 機能を広告し、サーバーがハッシュアルゴリズムXを使用してオブジェクトを処理できることをクライアントに通知できます。 指定しない場合、サーバーはSHA-1のみを処理すると見なされます。 クライアントがSHA-1以外のハッシュアルゴリズムを使用する場合は、object-formatの文字列を指定する必要があります。

session-id=<session id>

サーバーは、複数のリクエストにわたってこのプロセスを識別するために使用できるセッションIDを広告する場合があります。 クライアントは、自身のセッションIDをサーバーに広告することもできます。

セッションIDは、特定のプロセスに固有である必要があります。それらはパケット行内に収まる必要があり、印刷不可能な文字や空白文字を含めることはできません。 現在の実装ではtrace2セッションID(詳細は api-trace2 を参照)を使用していますが、これは変更される可能性があるため、セッションIDのユーザーはこの事実に依存しないでください。

object-info

object-info は、1つまたは複数のオブジェクトに関する情報を取得するためのコマンドです。 その主な目的は、クライアントがオブジェクトを完全にフェッチすることなく、この情報に基づいて決定を下せるようにすることです。 現在サポートされている情報はオブジェクトサイズのみです。

object-info リクエストは以下の引数を取ります:

size

リストされたオブジェクトIDごとに返されるサイズ情報を要求します。

oid <oid>

クライアントが情報を取得したいオブジェクトをサーバーに指示します。

object-info の応答は、要求されたオブジェクトIDと関連する要求された情報のリストであり、それぞれが1つのスペースで区切られています。

output = info flush-pkt
info = PKT-LINE(attrs) LF)
        *PKT-LINE(obj-info LF)
attrs = attr | attrs SP attrs
attr = "size"
obj-info = obj-id SP obj-size