设置和配置
获取和创建项目
基本快照
分支和合并
共享和更新项目
检查和比较
补丁
调试
电子邮件
外部系统
服务器管理
指南
- gitattributes
- 命令行界面约定
- 日常 Git
- 常见问题 (FAQ)
- 词汇表
- 钩子 (Hooks)
- .gitignore
- .gitmodules
- 修订版本
- 子模块
- 教程
- 工作流程
- 所有指南...
管理
底层命令
-
2.49.0
2025-03-14
- 2.48.1 无更改
-
2.48.0
2025-01-10
- 2.47.2 无更改
-
2.47.1
2024-11-25
- 2.45.1 → 2.47.0 无更改
-
2.45.0
2024-04-29
- 2.44.1 → 2.44.3 无更改
-
2.44.0
2024-02-23
- 2.43.1 → 2.43.6 无更改
-
2.43.0
2023-11-20
- 2.40.1 → 2.42.4 无更改
-
2.40.0
2023-03-12
- 2.38.1 → 2.39.5 无更改
-
2.38.0
2022-10-02
描述
本文档介绍了 Git Wire Protocol 版本 2 的规范。 协议 v2 将在以下方面改进 v1
-
单个服务将支持多个命令,而不是多个服务名称
-
易于扩展,因为功能被移动到协议的自身部分,不再隐藏在 NUL 字节之后,并且不受 pkt-line 大小的限制
-
分离隐藏在 NUL 字节后面的其他信息(例如,将代理字符串作为一种功能,可以使用 *ls-refs* 请求 symref)
-
除非明确请求,否则将省略引用广告
-
ls-refs 命令显式请求一些引用
-
专为 http 和无状态 RPC 设计。 借助清晰的刷新语义,http 远程助手可以简单地充当代理
在协议 v2 中,通信是面向命令的。 首次联系服务器时,将发布功能列表。 这些功能中的一些将是客户端可以请求执行的命令。 命令完成后,客户端可以重用连接并请求执行其他命令。
数据包行成帧
所有通信都使用数据包行成帧完成,就像在 v1 中一样。 有关更多信息,请参见 gitprotocol-pack[5] 和 gitprotocol-common[5]。
在协议 v2 中,这些特殊数据包将具有以下语义
-
0000 刷新数据包 (flush-pkt) - 指示消息结束
-
0001 分隔符数据包 (delim-pkt) - 分隔消息的各个部分
-
0002 响应结束数据包 (response-end-pkt) - 指示无状态连接的响应结束
初始客户端请求
通常,客户端可以通过发送 `version=2` 通过正在使用的传输的相应边信道来请求使用协议 v2,该信道不可避免地设置 `GIT_PROTOCOL`。 更多信息可以在 gitprotocol-pack[5] 和 gitprotocol-http[5] 以及 `git.txt` 中的 `GIT_PROTOCOL` 定义中找到。 在所有情况下,来自服务器的响应都是功能通告。
Git 传输
使用 git:// 传输时,可以通过发送 "version=2" 作为额外参数来请求使用协议 v2
003egit-upload-pack /project.git\0host=myserver.com\0\0version=2\0
HTTP 传输
使用 http:// 或 https:// 传输时,客户端按照 gitprotocol-http[5] 中的描述发出“智能” 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 也是一样的)。
使用 git-upload-pack[1] 的 --http-backend-info-refs
选项。
可能需要配置服务器以通过 GIT_PROTOCOL
变量传递此标头的内容。 请参见 git-http-backend.txt
中的讨论。
功能通告
决定使用协议版本 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
功能(采用 agent=X
的形式)以通知客户端服务器正在运行版本 X
。 客户端可以选择通过在其对服务器的请求中包含具有值 Y
的 agent
功能(采用 agent=Y
的形式)来发送其自己的代理字符串(但如果服务器未通告 agent 功能,则不得这样做)。 X
和 Y
字符串可以包含任何可打印的 ASCII 字符,除了空格(即,字节范围 33 ⇐ x ⇐ 126),并且通常采用 "package/version-os" 的形式(例如,"git/1.8.3.1-Linux"),其中 os
是操作系统名称(例如,“Linux”)。可以使用 GIT_USER_AGENT 环境变量配置 X
和 Y
,并且它具有优先级。 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 中获取包文件的命令。 可以将其视为 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) 分隔,每个部分都以其节标题开头。 大多数部分仅在发送包文件时发送。
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”开头
-
如果发送为 have 行的任何对象 ID 都不常见,则服务器将响应“NAK”。
-
对于所有作为通用行发送的对象 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" 开始。
-
如果请求了正深度,服务器将计算不深于所需深度的提交集合。
-
服务器为每个父提交不会在以下 packfile 中发送的提交发送一个 "shallow obj-id" 行。
-
服务器为客户端已指示为 shallow 的每个提交发送一个 "unshallow obj-id" 行,但由于 fetch 的结果(由于其父提交在以下 packfile 中发送),该提交不再是 shallow 的。
-
对于客户端未在其请求中指示为 shallow 的任何内容,服务器绝不能发送任何 "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" 开始。
-
服务器将为使用 *want-ref* 行请求的每个引用发送引用列表("<oid> <refname>")。
-
服务器绝不能发送任何未使用 *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 升级到新的哈希算法时,可能需要更新它。(它应该与 "pack\t" 或 "keep\t" 之后 index-pack 的输出相匹配。)
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
能力(以 object-format=X
的形式),以通知客户端服务器能够处理使用哈希算法 X 的对象。如果未指定,则假定服务器仅处理 SHA-1。如果客户端想要使用 SHA-1 以外的哈希算法,则应指定其 object-format 字符串。
session-id=<session-id>
服务器可以声明一个会话 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 列表以及关联的请求的信息,每个对象 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,从而 "seed" 并通知后续的 fetch
命令。
客户端可以在任何其他有效命令之前或之后发出 bundle-uri
。为了对客户端有用,预计它将在 ls-refs
之后和 fetch
之前发出,但可以在对话中的任何时间发出。
关于 bundle-uri 的讨论
该功能的目的是通过将 git-clone[1] 期间获取非常大的 PACK 的常见情况更改为较小的增量获取,从而优化常见情况下服务器资源的使用。
它还允许服务器与 uploadpack.packObjectsHook
结合使用实现更好的缓存(参见 git-config[1])。
通过让新的克隆或获取针对最近生成的 *.bundle 文件的提示进行更可预测和常见的协商。服务器甚至可以为 uploadpack.packObjectsHook
预生成此类协商的结果,因为新的推送会进入。
服务器可以利用这些 bundle 的一种方式是,服务器会预期新的克隆将下载已知的 bundle,然后使用在该 bundle(或多个 bundle)中找到的引用提示来赶上存储库的当前状态。
bundle-uri 的协议
一个 bundle-uri
请求不带任何参数,并且如上所述,当前不声明任何能力值。将来可能会添加两者。
当客户端发出一个 command=bundle-uri
请求时,响应是以数据包行形式提供的键值对列表,值为 <key>=<value>
。每个 <key>
都应解释为 bundle.*
命名空间中的配置键,以构建 bundle 列表。这些键按 bundle.<id>.
小节分组,其中每个对应于给定 <id>
的键都会为该 <id>
定义的 bundle 贡献属性。 有关这些键的具体详细信息以及 Git 客户端将如何解释其值,请参见 git-config[1]。
客户端必须按照上述格式解析该行,不符合格式的行应被丢弃。在这种情况下,可能会警告用户。
bundle-uri 客户端和服务器的期望
- URI 内容
-
声明的 URI 处的内容必须是以下两种类型之一。
声明的 URI 可能包含一个
git bundle verify
会接受的 bundle 文件。也就是说,它们必须包含一个或多个引用提示供客户端使用,必须使用标准 "-" 前缀指示先决条件(如果有),并且必须指示它们的 "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 数据(如果有)。
- bundle-uri 客户端到服务器
-
客户端应在任何后续的
fetch
请求中,将 bundle 标头中找到的引用提示作为 *have* 行提供。如果这样做被认为更糟糕,例如如果无法下载 bundle,则客户端也可以完全忽略 bundle,因为它不喜欢它找到的提示等等。 - 何时声明的 BUNDLE 不需要进一步协商
-
如果在发出
bundle-uri
和ls-refs
并获取 bundle 标头后,客户端发现它想要的引用提示可以完全从声明的 bundle 中检索,则客户端可以与 Git 服务器断开连接。这种 *clone* 或 *fetch* 的结果应该与不使用 bundle-uri 获得的状态无法区分。 - 早期客户端断开连接和错误恢复
-
客户端可能会在仍在下载 bundle 时执行早期断开连接(已流式传输和解析其标头)。在这种情况下,客户端必须优雅地从与完成 bundle 的下载和验证相关的任何错误中恢复。
也就是说,客户端可能需要重新连接并发出一个 *fetch* 命令,并且可能退回到完全不使用 *bundle-uri*。
这种 "MAY" 行为被指定为这样(而不是 "SHOULD"),因为假设声明 bundle uris 的服务器更有可能提供相对较大的存储库,并且指向很有可能正常工作的 URI。 客户端可以查看 bundle 的有效负载大小作为启发式方法,以查看是否值得提前断开连接,是否需要退回到完整的 "fetch" 对话。
- 何时声明的 BUNDLE 需要进一步协商
-
客户端应该使用声明的 bundle 中找到的 OID 提示,通过 "fetch" 命令开始与服务器协商 PACK,即使它仍在下载这些 bundle。
这允许从任何交互式服务器对话中进行积极的提前断开连接。客户端盲目地信任广告的 OID 提示是相关的,并将其作为have行发出,然后通过want行请求它想要的任何提示(通常来自“ls-refs”广告)。然后,服务器将计算一个(希望很小)PACK,其中包含来自 bundle 的提示与请求的数据之间的预期差异。
客户端随后需要保持活动的唯一连接是并发下载的静态 bundle。当这些 bundle 和增量 PACK 被检索时,应该对其进行解压缩和验证。此时的任何错误都应优雅地恢复,请参见上文。
bundle-uri 协议特性
客户端从服务器提供的 <key>=<value>
对中构建一个 bundle 列表。这些对是 bundle.*
命名空间的一部分,如 git-config[1] 中所记录的。在本节中,我们将讨论其中一些键,并描述客户端将响应此信息采取的行动。
特别是,bundle.version
键指定一个整数值。目前唯一接受的值是 1
,但如果客户端在此处看到意外的值,则客户端必须忽略该 bundle 列表。
只要理解了 bundle.version
,客户端可以忽略所有其他未知的键。服务器将保证与旧客户端的兼容性,尽管较新的客户端可能能够更好地使用额外的键来最大限度地减少下载。
任何向后不兼容的预 URI 键值添加都将受到新的 bundle.version
值或 bundle-uri 能力广告本身中的值,和/或未来新的 bundle-uri
请求参数的保护。
一些尚未实现但将来可能实现的键值对示例包括
-
添加 "hash=<val>" 或 "size=<bytes>" 来声明 bundle 文件的预期哈希或大小。
-
声明一个或多个 bundle 文件是相同的(例如,让客户端循环或以其他方式选择 N 个可能的文件中的一个)。
-
"oid=<OID>" 快捷方式和 "prerequisite=<OID>" 快捷方式。用于表达具有一个 tip 且没有先决条件,或一个 tip 和一个先决条件的 bundle 的常见情况。
这将允许优化服务器的常见情况,这些服务器希望提供一个仅包含其“主”分支和/或其增量更新的“大型 bundle”。
接收到此类响应的客户端可以假设他们可以跳过从指示 URI 处的 bundle 中检索标头,从而节省他们自己和服务器(s)检查该 bundle 或 bundle 的标头所需的请求。
promisor-remote=<pr-infos>
服务器可以向可能希望使用它们作为其 promisor remote 的客户端声明它正在使用或知道的一些 promisor remote,而不是此存储库。在这种情况下,<pr-infos> 应采用以下形式
pr-infos = pr-info | pr-infos ";" pr-info
pr-info = "name=" pr-name | "name=" pr-name "," "url=" pr-url
其中 pr-name
是 promisor remote 的 url 编码名称,pr-url
是该 promisor remote 的 url 编码 URL。
在这种情况下,如果客户端决定使用服务器声明的一个或多个 promisor remote,它可以回复 "promisor-remote=<pr-names>",其中 <pr-names> 应采用以下形式
pr-names = pr-name | pr-names ";" pr-name
其中 pr-name
是服务器声明且客户端接受的 promisor remote 的 url 编码名称。
请注意,在本文档中的任何地方,pr-name
必须是有效的远程名称,并且如果 ; 和 , 字符出现在 pr-name
或 pr-url
中,则必须对其进行编码。
如果服务器不知道任何可能对客户端有益的 promisor remote,或者更希望客户端不要使用它正在使用或知道的任何 promisor remote,则它根本不应声明 "promisor-remote" 功能。
在这种情况下,或者如果客户端不想使用服务器声明的任何 promisor remote,则客户端不应在其回复中声明 "promisor-remote" 功能。
服务器和客户端可以使用 "promisor.advertise" 和 "promisor.acceptFromServer" 配置选项来控制它们分别声明或接受的内容。有关更多信息,请参阅这些配置选项的文档。
请注意,将来如果服务器在响应 git fetch
或 git clone
时可以使用 "promisor-remote" 协议功能来声明客户端可以用作 promisor remote 的更好连接的 remote,而不是此存储库,那就太好了,以便客户端可以从这些其他更好连接的 remote 中延迟获取对象。这将要求服务器在其响应中省略客户端已接受的更好连接的 remote 上可用的对象。但是,这尚未实现。因此,目前此 "promisor-remote" 功能仅在服务器声明它已经使用的一些 promisor remote 来借用对象时才有用。
GIT
是 git[1] 套件的一部分