簡體中文 ▾ 主題 ▾ 最新版本 ▾ gitprotocol-v2 上次更新於 2.52.0

名稱

gitprotocol-v2 - Git Wire Protocol, Version 2

概要

<over-the-wire-protocol>

描述

本文件介紹了 Git Wire Protocol 第 2 版的規範。協議 v2 將在以下方面改進 v1:

  • 單個服務將支援多個命令,而不是多個服務名稱。

  • 易於擴充套件,因為功能被移到了協議的獨立部分,不再隱藏在 NUL 位元組後面並受限於 pkt-line 的大小。

  • 將隱藏在 NUL 位元組後面的其他資訊(例如,代理字串作為功能,可以使用 ls-refs 請求 symrefs)分開。

  • 除非明確要求,否則將省略引用廣告。

  • ls-refs 命令,用於顯式請求一些引用。

  • 為 http 和無狀態 rpc 而設計。透過清晰的 flush 語義,http 遠端輔助工具可以簡單地充當代理。

在協議 v2 中,通訊是面向命令的。首次聯絡伺服器時,將廣告一系列功能。其中一些功能是客戶端可以請求執行的命令。一旦命令完成,客戶端就可以重用連線並請求執行其他命令。

包行幀

所有通訊都使用包行幀進行,與 v1 相同。有關更多資訊,請參閱 gitprotocol-pack[5]gitprotocol-common[5]

在協議 v2 中,這些特殊包將具有以下語義:

  • 0000 Flush Packet (flush-pkt) - 表示訊息的結束。

  • 0001 Delimiter Packet (delim-pkt) - 分隔訊息的各個部分。

  • 0002 Response End Packet (response-end-pkt) - 表示無狀態連線響應的結束。

初始客戶端請求

通常,客戶端可以透過傳輸通道傳送 version=2 來請求使用協議 v2,該通道會最終設定 GIT_PROTOCOL。有關更多資訊,請參閱 gitprotocol-pack[5]gitprotocol-http[5],以及 git[1]GIT_PROTOCOL 的定義。在所有情況下,伺服器的響應都是功能廣告。

Git 傳輸

使用 git:// 傳輸時,可以透過傳送“version=2”作為附加引數來請求使用協議 v2。

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

SSH 和檔案傳輸

使用 ssh:// 或 file:// 傳輸時,必須將 GIT_PROTOCOL 環境變數顯式設定為包含“version=2”。伺服器可能需要配置為允許此環境變數透過。

HTTP 傳輸

使用 http:// 或 https:// 傳輸時,客戶端會發出一個“智慧”的 info/refs 請求,如 gitprotocol-http[5] 中所述,並透過在 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,情況相同)。

使用 git-upload-pack[1]--http-backend-info-refs 選項。

伺服器可能需要配置為透過 GIT_PROTOCOL 變數傳遞此標頭的內容。請參閱 git-http-backend[1] 中的討論。

功能廣告

決定使用協議版本 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 | " -_.,?\/{}[]()<>!@#$%^&*+=:;")

命令請求

收到功能廣告後,客戶端可以發出請求,選擇它想要的命令,並附帶任何特定功能或引數。然後有一個可選部分,客戶端可以在其中提供任何特定於命令的引數或查詢。一次只能請求一個命令。

request = empty-request | command-request
empty-request = flush-pkt
command-request = command
    capability-list
    delim-pkt
    command-args
    flush-pkt
command = PKT-LINE("command=" key LF)
command-args = *command-specific-arg
command-specific-args are packet line framed arguments defined by
each individual command.

伺服器將檢查客戶端的請求是否由有效的命令和已廣告的有效功能組成。如果請求有效,伺服器將執行該命令。伺服器必須在收到客戶端的整個請求後再發出響應。響應的格式由正在執行的命令確定,但在所有情況下,flush-pkt 都表示響應的結束。

當命令完成後,並且客戶端已收到伺服器的完整響應後,客戶端可以請求執行另一個命令,或者終止連線。客戶端可以傳送一個僅包含 flush-pkt 的空請求,表示不再發送請求。

功能

有兩種不同型別的能力:普通能力,用於傳達資訊或改變請求的行為;以及命令,這是客戶端想要執行的核心操作(fetch、push 等)。

協議版本 2 預設是無狀態的。這意味著所有命令在伺服器端都必須只持續一個回合並且是無狀態的,除非客戶端已請求指示伺服器應維護狀態的能力。客戶端為了正確執行,不得要求伺服器端進行狀態管理。這允許伺服器端進行簡單的輪詢負載均衡,而無需擔心狀態管理。

agent

伺服器可以透過值 X(形式為 agent=X)廣告 agent 功能,以通知客戶端伺服器正在執行版本 X。客戶端可以透過在其請求中包含值 Y(形式為 agent=Y)的 agent 功能來選擇性地傳送自己的代理字串(但如果伺服器未廣告代理功能,則不能這樣做)。XY 字串可以包含除空格以外的任何可列印 ASCII 字元(即,位元組範圍 33 ⇐ x ⇐ 126),通常形式為“package/version-os”(例如,“git/1.8.3.1-Linux”),其中 os 是作業系統名稱(例如,“Linux”)。XY 可以透過 GIT_USER_AGENT 環境變數配置,並且具有更高的優先順序。os 是使用 uname(2) 系統呼叫或其等效項的 sysname 欄位檢索的。代理字串僅用於統計和除錯目的,不得用於以程式設計方式假定存在或不存在特定功能。

ls-refs

ls-refs 是 v2 中用於請求引用廣告的命令。與當前的引用廣告不同,ls-refs 接受引數,可用於限制從伺服器傳送的引用。

基礎命令中不支援的附加功能將作為命令的值在功能廣告中以空格分隔的列表形式進行廣告:“<command>=<feature-1> <feature-2>”。

ls-refs 接受以下引數:

   symrefs
In addition to the object pointed by it, show the underlying ref
pointed by it when showing a symbolic ref.
   peel
Show peeled tags.
   ref-prefix <prefix>
When specified, only references having a prefix matching one of
the provided prefixes are displayed. Multiple instances may be
given, in which case references matching any prefix will be
shown. Note that this is purely for optimization; a server MAY
show refs not matching the prefix if it chooses, and clients
should filter the result themselves.

如果廣告了 unborn 功能,則可以在客戶端的請求中包含以下引數。

   unborn
The server will send information about HEAD even if it is a symref
pointing to an unborn branch in the form "unborn HEAD
symref-target:<target>".

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 中用於獲取 packfile 的命令。可以將其視為 v1 fetch 的修改版本,其中剝離了 ref-advertisement(因為 ls-refs 命令扮演該角色),並且訊息格式進行了調整,以消除冗餘並允許輕鬆新增未來的擴充套件。

基礎命令中不支援的附加功能將作為命令的值在功能廣告中以空格分隔的列表形式進行廣告:“<command>=<feature-1> <feature-2>”。

fetch 請求可以接受以下引數:

   want <oid>
Indicates to the server an object which the client wants to
retrieve.  Wants can be anything and are not limited to
advertised objects.
   have <oid>
Indicates to the server an object which the client has locally.
This allows the server to make a packfile which only contains
the objects that the client needs. Multiple 'have' lines can be
supplied.
   done
Indicates to the server that negotiation should terminate (or
not even begin if performing a clone) and that the server should
use the information supplied in the request to construct the
packfile.
   thin-pack
Request that a thin pack be sent, which is a pack with deltas
which reference base objects not contained within the pack (but
are known to exist at the receiving end). This can reduce the
network traffic significantly, but it requires the receiving end
to know how to "thicken" these packs by adding the missing bases
to the pack.
   no-progress
Request that progress information that would normally be sent on
side-band channel 2, during the packfile transfer, should not be
sent.  However, the side-band channel 3 is still used for error
responses.
   include-tag
Request that annotated tags should be sent if the objects they
point to are being sent.
   ofs-delta
Indicate that the client understands PACKv2 with delta referring
to its base by position in pack rather than by an oid.  That is,
they can read OBJ_OFS_DELTA (aka type 6) in a packfile.

如果廣告了 shallow 功能,則可以在客戶端的請求中包含以下引數,以及伺服器響應中 shallow-info 部分的潛在新增(如下所述)。

   shallow <oid>
A client must notify the server of all commits for which it only
has shallow copies (meaning that it doesn't have the parents of
a commit) by supplying a 'shallow <oid>' line for each such
object so that the server is aware of the limitations of the
client's history.  This is so that the server is aware that the
client may not have all objects reachable from such commits.
   deepen <depth>
Requests that the fetch/clone should be shallow having a commit
depth of <depth> relative to the remote side.
   deepen-relative
Requests that the semantics of the "deepen" command be changed
to indicate that the depth requested is relative to the client's
current shallow boundary, instead of relative to the requested
commits.
   deepen-since <timestamp>
Requests that the shallow clone/fetch should be cut at a
specific time, instead of depth.  Internally it's equivalent to
doing "git rev-list --max-age=<timestamp>". Cannot be used with
"deepen".
   deepen-not <rev>
Requests that the shallow clone/fetch should be cut at a
specific revision specified by '<rev>', instead of a depth.
Internally it's equivalent of doing "git rev-list --not <rev>".
Cannot be used with "deepen", but can be used with
"deepen-since".

如果廣告了 filter 功能,則可以在客戶端的請求中包含以下引數:

   filter <filter-spec>
Request that various objects from the packfile be omitted
using one of several filtering techniques. These are intended
for use with partial clone and partial fetch operations. See
`rev-list` for possible "filter-spec" values. When communicating
with other processes, senders SHOULD translate scaled integers
(e.g. "1k") into a fully-expanded form (e.g. "1024") to aid
interoperability with older receivers that may not understand
newly-invented scaling suffixes. However, receivers SHOULD
accept the following suffixes: 'k', 'm', and 'g' for 1024,
1048576, and 1073741824, respectively.

如果廣告了 ref-in-want 功能,則可以在客戶端的請求中包含以下引數,以及伺服器響應中 wanted-refs 部分的潛在新增(如下所述)。

   want-ref <ref>
Indicates to the server that the client wants to retrieve a
particular ref, where <ref> is the full name of a ref on the
server.  It is a protocol error to send want-ref for the
same ref more than once.

如果廣告了 sideband-all 功能,則可以在客戶端的請求中包含以下引數:

   sideband-all
Instruct the server to send the whole response multiplexed, not just
the packfile section. All non-flush and non-delim PKT-LINE in the
response (not only in the packfile section) will then start with a byte
indicating its sideband (1, 2, or 3), and the server may send "0005\2"
(a PKT-LINE of sideband 2 with no payload) as a keepalive packet.

如果廣告了 packfile-uris 功能,則可以在客戶端的請求中包含以下引數,以及伺服器響應中 packfile-uris 部分的潛在新增(如下所述)。請注意,最多隻能向伺服器傳送一行 packfile-uris

   packfile-uris <comma-separated-list-of-protocols>
Indicates to the server that the client is willing to receive
URIs of any of the given protocols in place of objects in the
sent packfile. Before performing the connectivity check, the
client should download from all given URIs. Currently, the
protocols supported are "http" and "https".

如果廣告了 wait-for-done 功能,則可以在客戶端的請求中包含以下引數。

   wait-for-done
Indicates to the server that it should never send "ready", but
should wait for the client to say "done" before sending the
packfile.

fetch 的響應被分成多個部分,由分隔符包(0001)分隔,每個部分都以其部分標頭開始。大多數部分僅在傳送 packfile 時傳送。

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
* If the client determines that it is finished with negotiations by
  sending a "done" line (thus requiring the server to send a packfile),
  the acknowledgments sections MUST be omitted from the server's
  response.
  • 始終以“acknowledgments”部分標頭開頭。

  • 如果沒有傳送的 object id 都不是通用的,伺服器將回復“NAK”。

  • 對於所有傳送的 object id 並且是通用的,伺服器將回復“ACK obj-id”。

  • 響應不能同時包含“ACK”行和“NAK”行。

  • 伺服器將回復“ready”行,表示伺服器已找到可接受的公共基礎,並已準備好建立和傳送 packfile(將在同一響應的 packfile 部分中找到)。

  • 如果伺服器找到了合適的切入點並決定傳送“ready”行,那麼伺服器可以選擇(作為一種最佳化)省略其響應中會發送的任何“ACK”行。這是因為伺服器已經確定了它計劃傳送給客戶端的物件,並且不再需要進一步的協商。

       shallow-info section
    * If the client has requested a shallow fetch/clone, a shallow
      client requests a fetch or the server is shallow then the
      server's response may include a shallow-info section.  The
      shallow-info section will be included if (due to one of the
      above conditions) the server needs to inform the client of any
      shallow boundaries or adjustments to the clients already
      existing shallow boundaries.
  • 始終以“shallow-info”部分標頭開頭。

  • 如果請求了正深度,伺服器將計算深度不超過所需深度的提交集。

  • 伺服器將傳送一個“shallow obj-id”行,對應於其父物件將在後續 packfile 中傳送的每個提交。

  • 伺服器將傳送一個“unshallow obj-id”行,對應於客戶端已指示為淺但由於 fetch(由於其父物件在後續 packfile 中傳送)而不再為淺的每個提交。

  • 伺服器不得傳送任何“unshallow”行,這些行是客戶端在其請求中未指示為淺的。

       wanted-refs section
    * This section is only included if the client has requested a
      ref using a 'want-ref' line and if a packfile section is also
      included in the response.
  • 始終以“wanted-refs”部分標頭開頭。

  • 伺服器將傳送一個引用列表(“<oid> <refname>”),對應於使用 want-ref 行請求的每個引用。

  • 伺服器不得傳送任何未透過 want-ref 行請求的引用。

       packfile-uris section
    * This section is only included if the client sent
      'packfile-uris' and the server has at least one such URI to
      send.
  • 始終以“packfile-uris”部分標頭開頭。

  • 對於伺服器傳送的每個 URI,它會發送 pack 內容的雜湊(由 git index-pack 輸出)以及 URI。

  • 雜湊長度為 40 個十六進位制字元。當 Git 升級到新的雜湊演算法時,可能需要更新此內容。(它應該匹配 index-pack 輸出的“pack\t”或“keep\t”之後的內容)。

       packfile section
    * This section is only included if the client has sent 'want'
      lines in its request and either requested that no more
      negotiation be done by sending 'done' or if the server has
      decided it has found a sufficient cut point to produce a
      packfile.
  • 始終以“packfile”部分標頭開頭。

  • packfile 的傳輸立即在部分標頭之後開始。

  • packfile 的資料傳輸始終是多路複用的,使用與協議版本 1 中的 side-band-64k 功能相同的語義。這意味著在 packfile 資料流中的每個資料包都由一個前導的 4 位元組 pkt-line 長度(對於 pkt-line 格式很常見)、一個 1 位元組的流程式碼以及實際資料組成。

     The stream code can be one of:
    1 - pack data
    2 - progress messages
    3 - fatal error message just before stream aborts

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 是檢索有關一個或多個物件的資訊的命令。其主要目的是允許客戶端在不完全獲取物件的情況下基於此資訊做出決策。物件大小是目前唯一支援的資訊。

object-info 請求接受以下引數:

size
Requests size information to be returned for each listed object id.
oid <oid>
Indicates to the server an object which the client wants to obtain
information for.

object-info 的響應是請求的物件 ID 和相關資訊的列表,每個之間用一個空格分隔。

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

bundle-uri

如果廣告了 bundle-uri 功能,則伺服器支援 'bundle-uri' 命令。

該功能目前以無值廣告(即不是“bundle-uri=somevalue”),未來可能會新增值以支援命令範圍的擴充套件。客戶端必須忽略任何未知的功能值,並繼續進行它們支援的 'bundle-uri' 對話。

bundle-uri 命令旨在在 fetch 之前發出,以獲取 bundle 檔案(請參閱 git-bundle[1])的 URI,以“種子”和告知後續的 fetch 命令。

客戶端可以在任何其他有效命令之前或之後發出 bundle-uri。為了對客戶端有用,預計它將在 ls-refs 之後發出,並在 fetch 之前發出,但可以在對話的任何時候發出。

bundle-uri 討論

該功能旨在透過將 git-clone[1] 中非常大的 PACK 的常見獲取情況轉換為更小的增量獲取,來最佳化伺服器資源消耗。

它還允許伺服器在與 uploadpack.packObjectsHook(請參閱 git-config[1])結合使用時實現更好的快取。

透過使新的克隆或獲取能夠更可預測地、更常規地與最近生成的 *.bundle 檔案進行協商。伺服器甚至可以在新的推送到來時,為 uploadpack.packObjectsHook 預先生成此類協商的結果。

伺服器可以利用這些 bundle 的一種方式是:伺服器期望新的克隆下載一個已知的 bundle,然後透過該 bundle(或 bundles)中找到的 ref 提示來追趕儲存庫的當前狀態。

bundle-uri 協議

bundle-uri 請求不帶引數,如上所述,目前不廣告功能值。兩者都可能在未來新增。

當客戶端發出 command=bundle-uri 請求時,響應是作為包行提供的鍵值對列表,值為 <key>=<value>。每個 <key> 都應解釋為 bundle.* 名稱空間中的配置鍵,以構建 bundle 列表。這些鍵按 bundle.<id>. 子部分分組,其中對應於給定 <id> 的每個鍵都為由該 <id> 定義的 bundle 貢獻屬性。請參閱 git-config[1] 以瞭解這些鍵的具體詳細資訊以及 Git 客戶端如何解釋它們的值。

客戶端必須按照上述格式解析行,不符合格式的行應被丟棄。在這種情況下,使用者可能會收到警告。

bundle-uri 客戶端和伺服器的期望

URI 內容

廣告 URI 中的內容必須是以下兩種型別之一:

廣告的 URI 可以包含一個 bundle 檔案,該檔案是 git bundle verify 可以接受的。即,它們必須包含一個或多個引用提示供客戶端使用,必須指示任何先決條件(如果有)使用標準的 "-" 字首,並且必須指示其“object-format”(如果適用)。

廣告的 URI 也可以包含一個純文字檔案,該檔案是 git config --list(使用 --file 選項)可以接受的。此列表中的鍵值對屬於 bundle.* 名稱空間(請參閱 git-config[1])。

bundle-uri 客戶端錯誤恢復

客戶端必須首先優雅地處理錯誤,無論錯誤是由於 bundle URI 中的資料缺失/損壞,還是因為客戶端太笨而無法理解和完全解析 bundle 標頭及其先決條件關係,或其他原因。

伺服器操作員應該有信心啟用“bundle-uri”而不用擔心,例如,如果他們的 CDN 出現故障,克隆或獲取將面臨硬性失敗。即使伺服器 bundle 不完整或有某種缺陷,客戶端也應該能夠得到一個可用的儲存庫,就像它選擇不使用此協議擴充套件一樣。

所有後續關於客戶端和伺服器互動的討論都必須牢記這一點。

bundle-uri 伺服器到客戶端

返回的 bundle uri 的順序不重要。客戶端必須解析其標頭以發現其包含的 OID 和先決條件。客戶端必須將 bundle 的內容本身及其標頭視為最終真相來源。

伺服器甚至可以返回與正在克隆的儲存庫沒有任何直接關係的 bundle(無論是意外還是有意“巧妙”配置),並期望客戶端從中找出它想要的資料,如果有的話。

bundle-uri 客戶端到伺服器

客戶端應將 bundle 標頭中找到的引用提示作為 have 行提供給任何後續的 fetch 請求。客戶端也可以選擇完全忽略 bundle,如果這樣做被認為弊大於利(例如,如果 bundle 無法下載,它不喜歡它找到的提示等)。

已廣告的 bundle 不需要進一步協商時

如果發出 bundle-urils-refs,並獲取了 bundle 的標頭後,客戶端發現它想要的 ref 提示可以完全從已廣告的 bundle 中檢索,客戶端可以斷開與 Git 伺服器的連線。此類 clonefetch 的結果應該與未使用 bundle-uri 達到的狀態無法區分。

早期客戶端斷開連線和錯誤恢復

客戶端在下載 bundle 時(已流式傳輸並解析其標頭)可以執行早期斷開連線。在這種情況下,客戶端必須能夠從與完成 bundle 下載和驗證相關的任何錯誤中優雅地恢復。

即,客戶端可能需要重新連線併發出 fetch 命令,並且可能退而求其次,根本不使用 bundle-uri

之所以將此“MAY”行為指定為如此(而不是“SHOULD”),是因為假設廣告 bundle uri 的伺服器更有可能託管一個相對較大的儲存庫,並且指向有機會正常工作的 URI。客戶端可以(例如)檢視 bundle 的有效負載大小作為一種啟發式方法,以確定在必要時回退到完整的“fetch”對話是否值得。

已廣告的 bundle 需要進一步協商時

客戶端應透過“fetch”命令,使用廣告 bundle 中找到的 OID 提示,開始與伺服器進行 PACK 的協商,即使它仍在下載該 bundle。

這允許從任何互動式伺服器對話中積極地早期斷開連線。客戶端盲目地信任廣告的 OID 提示是相關的,並將它們作為 have 行發出,然後它透過 want 行請求它想要的任何提示(通常來自“ls-refs”廣告)。然後,伺服器將建立一個(希望很小的)PACK,其中包含 bundle 提示和請求資料之間的預期差異。

客戶端唯一需要保持連線的是與併發下載的靜態 bundle。當這些 bundle 和增量 PACK 被檢索後,它們應該被解壓和驗證。此時的任何錯誤都應被優雅地恢復,請參閱上文。

bundle-uri 協議功能

客戶端從伺服器提供的 <key>=<value> 對構建 bundle 列表。這些對屬於 git-config[1] 中記錄的 bundle.* 名稱空間。在本節中,我們將討論其中一些鍵,並描述客戶端根據這些資訊將執行的操作。

特別是,bundle.version 鍵指定一個整數值。目前唯一接受的值是 1,但如果客戶端在此處看到意外值,則客戶端必須忽略 bundle 列表。

只要 bundle.version 被理解,所有其他未知鍵都可以被客戶端忽略。伺服器將保證與舊版客戶端相容,儘管新版客戶端可能能夠更好地利用額外部索引鍵來最小化下載。

任何向後不相容的 URI 前鍵值對新增都將由新的 bundle.version 值或 bundle-uri 功能廣告本身中的值,以及/或新的未來 bundle-uri 請求引數來保護。

目前未實現但未來可能實現的示例鍵值對包括:

  • 新增“hash=<val>”或“size=<bytes>”以廣告 bundle 檔案的預期雜湊或大小。

  • 廣告一個或多個 bundle 檔案相同(例如,讓客戶端輪詢或以其他方式選擇 N 個可能檔案中的一個)。

  • 一個“oid=<OID>”快捷方式和“prerequisite=<OID>”快捷方式。用於表示具有單個提示且無先決條件的 bundle,或具有單個提示和一個先決條件的 bundle 的常見情況。

    這將允許最佳化伺服器的常見情況,即伺服器希望提供一個僅包含其“主”分支的“大 bundle”,以及/或其增量更新。

    收到此類響應的客戶端可以假設它們可以跳過從指定 URI 的 bundle 中檢索標頭,從而為自己和伺服器節省檢查該 bundle 或 bundle 標頭的請求。

promisor-remote=<pr-info>

伺服器可能會向客戶端廣告它正在使用或知道的一些 promisor remote,客戶端可以使用它們作為其 promisor remote,而不是當前儲存庫。在這種情況下,<pr-info> 應採用以下形式:

pr-info = pr-fields | pr-info ";" pr-fields
pr-fields = pr-field | pr-fields "," pr-field
pr-field = field-name "=" field-value

其中,在給定的 pr-fields 中,所有 field-namefield-value 都是與單個 promisor remote 相關的欄位名稱和值。給定的 field-name 在給定的 pr-fields 中不得出現一次以上。

伺服器必須在每個 pr-fields 中至少廣告“name”和“url”欄位名稱以及相關欄位值,它們是有效遠端的名稱及其 URL。“name”和“url”欄位必須首先出現在每個 pr-fields 中,並按此順序。

在這些強制欄位之後,伺服器可以按任意順序廣告以下可選欄位:

partialCloneFilter

遠端使用的過濾器規範。客戶端可以使用此來確定遠端的過濾策略是否與它們的需求相容(例如,檢查兩者是否都使用“blob:none”)。它對應於“remote.<name>.partialCloneFilter”配置設定。

token

客戶端連線到遠端時可以使用的身份驗證令牌。它對應於“remote.<name>.token”配置設定。

目前協議未定義其他欄位。欄位名稱區分大小寫,並且必須完全按照上述規定傳輸。客戶端必須忽略它們不識別的欄位,以便允許未來的協議擴充套件。

目前,客戶端只能使用透過這些欄位傳輸的資訊來決定是否接受廣告的 promisor remote。未來,這些資訊可能會用於其他目的。

欄位值必須經過 urlencode。

如果客戶端決定使用一個或多個伺服器廣告的 promisor remote,它可以用“promisor-remote=<pr-names>”進行回覆,其中 <pr-names> 應採用以下形式:

pr-names = pr-name | pr-names ";" pr-name

其中 pr-name 是伺服器廣告且客戶端接受的 promisor remote 的 urlencode 名稱。

請注意,在此文件的任何地方,如果 ;, 字元出現在 pr-namefield-value 中,則必須對其進行編碼。

如果伺服器不知道任何對客戶端有益的 promisor remote,或者更願意客戶端不使用它使用或知道的任何 promisor remote,則它不應廣告“promisor-remote”功能。

在這種情況下,或者如果客戶端不想使用伺服器廣告的任何 promisor remote,客戶端不應在其回覆中廣告“promisor-remote”功能。

在伺服器端,“promisor.advertise”和“promisor.sendFields”配置選項可用於控制其廣告的內容。在客戶端,“promisor.acceptFromServer”配置選項可用於控制其接受的內容。有關更多資訊,請參閱這些配置選項的文件。

請注意,將來,伺服器可以在響應 git fetchgit clone 時使用“promisor-remote”協議功能來廣告連線更好的遠端,客戶端可以使用這些遠端作為 promisor remote,而不是當前儲存庫,以便客戶端可以從這些其他連線更好的遠端懶惰地獲取物件。這需要伺服器在其響應中省略在客戶端已接受的連線更好的遠端上可用的物件。但這尚未實現。因此,目前此“promisor-remote”功能僅在伺服器廣告其已用於借用物件的某些 promisor remote 時有用。

GIT

Git[1] 套件的一部分