Git 协议 v1 和 v0、v2 有什么区别?
What's the difference between Git protocol v1 and v0,v2?
如果我使用协议 v0 和 v2 克隆一个存储库,一切正常。
但是如果我将协议更改为 v1,我会得到这个:
$GIT_TRACE_PACKET=1 git clone -c protocol.version=1 https://gitee.com/yomorun/yomo.git out
Cloning into 'out'...
16:57:10.089707 pkt-line.c:80 packet: git< version 1
fatal: invalid server response; got 'version 1'
错误信息来自check_smart_http()方法,我知道v2协议和v0协议都是智能协议,但是v1智能协议不一样吗?
这里我post一个Git的源代码片段:
static void check_smart_http(struct discovery *d, const char *service,
struct strbuf *type)
{
const char *p;
struct packet_reader reader;
warning(" remote-curl.c call [check_smart_http]");
/*
* If we don't see x-$service-advertisement, then it's not smart-http.
* But once we do, we commit to it and assume any other protocol
* violations are hard errors.
*/
if (!skip_prefix(type->buf, "application/x-", &p) ||
!skip_prefix(p, service, &p) ||
strcmp(p, "-advertisement"))
return;
packet_reader_init(&reader, -1, d->buf, d->len,
PACKET_READ_CHOMP_NEWLINE |
PACKET_READ_DIE_ON_ERR_PACKET);
if (packet_reader_read(&reader) != PACKET_READ_NORMAL)
die(_("invalid server response; expected service, got flush packet"));
if (skip_prefix(reader.line, "# service=", &p) && !strcmp(p, service)) {
/*
* The header can include additional metadata lines, up
* until a packet flush marker. Ignore these now, but
* in the future we might start to scan them.
*/
for (;;) {
packet_reader_read(&reader);
if (reader.pktlen <= 0) {
break;
}
}
/*
* v0 smart http; callers expect us to soak up the
* service and header packets
*/
d->buf = reader.src_buffer;
d->len = reader.src_len;
d->proto_git = 1;
} else if (!strcmp(reader.line, "version 2")) {
/*
* v2 smart http; do not consume version packet, which will
* be handled elsewhere.
*/
d->proto_git = 1;
} else {
die(_("invalid server response; got '%s'"), reader.line);
}
}
我不明白为什么它忽略了版本 1。
版本 Git 协议 v1 和版本 2 之间的差异是,
本文档介绍了 Git 有线协议第 2 版的规范。协议 v2 将在以下方面改进 v1:
单个服务将支持多个命令,而不是多个服务名称
随着功能被移动到协议的自己的部分,可以轻松扩展,不再隐藏在 NUL 字节后面并受 pkt 行大小的限制
分离出隐藏在 NUL 字节后面的其他信息(例如,作为功能的代理字符串和可以使用 ls-refs 请求的 symrefs)
除非明确要求,否则将省略参考广告
ls-refs 命令显式请求一些 refs
设计时考虑到了 http 和 stateless-rpc。有了清晰的刷新语义,http 远程助手可以简单地充当代理
在协议 v2 中,通信是面向命令的。首次联系服务器时,将公布功能列表。其中一些功能将是客户端可以请求执行的命令。命令完成后,客户端可以重用连接并请求执行其他命令。
Git 文档中有关协议 v2 的更多信息,
https://git-scm.com/docs/protocol-v2
没有“Git 协议 v1”。有零版本,这是第一个版本(如果需要,您可以 调用 “v1”,但 Git 不需要);然后是version 2,也就是第二个版本。所以有效的选择是 v0 和 v2。
“协议 v1”在 commit aa9bab2(Gti 2.16.0,2017 年 10 月)中引入
Protocol version 1 is simply the original and current protocol (what I'm
calling version 0) with the addition of a single packet line, which
precedes the ref advertisement, indicating the protocol version being
spoken.
由于 v2 改进了 v1,因此不再直接支持 v1:它是 v0 或 v2。
关于 v2,在 Git 2.34(2021 年第 4 季度)中,http-backend 已更新为在对方请求时自动启用协议 v2,利用 CGI 接口。
参见 commit 1b421e7, commit 2834a72, commit 295d81b, commit ff6a37c, commit 2614698 (10 Sep 2021) by Jeff King (peff
)。
(由 Junio C Hamano -- gitster
-- in commit cabb41d 合并,2021 年 9 月 23 日)
docs/http-backend
: mention v2 protocol
Signed-off-by: Jeff King
Historically there was a little bit of configuration needed at the webserver level in order to get the client's v2 protocol probes to Git.
But when we introduced the v2 protocol, we never documented these.
As of the previous commit, this should mostly work out of the box without any explicit configuration.
But it's worth documenting this to make it clear how we expect it to work, especially in the face of webservers which don't provide all headers over the CGI interface.
Or anybody who runs across this documentation but has an older version of Git (or used to have an older version, and wonders why they still have a SetEnvIf
line in their Apache config and whether it's still necessary).
git http-backend
现在包含在其 man page 中:
taking advantage of the CGI interface, It also supports Git's
more-efficient "v2" protocol if properly configured;
git http-backend
现在包含在其 man page 中:
# This is not strictly necessary using Apache and a modern version of
# git-http-backend, as the webserver will pass along the header in the
# environment as HTTP_GIT_PROTOCOL, and http-backend will copy that into
# GIT_PROTOCOL. But you may need this line (or something similar if you
# are using a different webserver), or if you want to support older Git
# versions that did not do that copying.
#
# Having the webserver set up GIT_PROTOCOL is perfectly fine even with
# modern versions (and will take precedence over HTTP_GIT_PROTOCOL,
# which means it can be used to override the client's request).
SetEnvIf Git-Protocol ".*" GIT_PROTOCOL=[=10=]
git http-backend
现在包含在其 man page 中:
Clients may probe for optional protocol capabilities (like the v2
protocol) using the Git-Protocol
HTTP header. In order to support
these, the contents of that header must appear in the GIT_PROTOCOL
environment variable. Most webservers will pass this header to the CGI
via the HTTP_GIT_PROTOCOL
variable, and git-http-backend
will
automatically copy that to GIT_PROTOCOL
. However, some webservers may
be more selective about which headers they'll pass, in which case they
need to be configured explicitly (see the mention of Git-Protocol
in
the Apache config from the earlier EXAMPLES section).
git -c protocol.version=1 clone...
曾经在 t/interop/i5700-protocol-transition.sh
中工作,但仅适用于 Got 2.0.0,而不是之后。
那是因为它是互操作测试:
This directory has interoperability tests for git.
Each script is
similar to the normal test scripts found in t/
, but with the added twist
that two special versions of git, "git.a
" and "git.b
", are available in
the PATH
.
Individual tests can then check the interaction between the two versions.
所以 protocol.version=1
只适用于 Git 2.0.0。不是之前也不是之后。
如果我使用协议 v0 和 v2 克隆一个存储库,一切正常。 但是如果我将协议更改为 v1,我会得到这个:
$GIT_TRACE_PACKET=1 git clone -c protocol.version=1 https://gitee.com/yomorun/yomo.git out
Cloning into 'out'...
16:57:10.089707 pkt-line.c:80 packet: git< version 1
fatal: invalid server response; got 'version 1'
错误信息来自check_smart_http()方法,我知道v2协议和v0协议都是智能协议,但是v1智能协议不一样吗?
这里我post一个Git的源代码片段:
static void check_smart_http(struct discovery *d, const char *service,
struct strbuf *type)
{
const char *p;
struct packet_reader reader;
warning(" remote-curl.c call [check_smart_http]");
/*
* If we don't see x-$service-advertisement, then it's not smart-http.
* But once we do, we commit to it and assume any other protocol
* violations are hard errors.
*/
if (!skip_prefix(type->buf, "application/x-", &p) ||
!skip_prefix(p, service, &p) ||
strcmp(p, "-advertisement"))
return;
packet_reader_init(&reader, -1, d->buf, d->len,
PACKET_READ_CHOMP_NEWLINE |
PACKET_READ_DIE_ON_ERR_PACKET);
if (packet_reader_read(&reader) != PACKET_READ_NORMAL)
die(_("invalid server response; expected service, got flush packet"));
if (skip_prefix(reader.line, "# service=", &p) && !strcmp(p, service)) {
/*
* The header can include additional metadata lines, up
* until a packet flush marker. Ignore these now, but
* in the future we might start to scan them.
*/
for (;;) {
packet_reader_read(&reader);
if (reader.pktlen <= 0) {
break;
}
}
/*
* v0 smart http; callers expect us to soak up the
* service and header packets
*/
d->buf = reader.src_buffer;
d->len = reader.src_len;
d->proto_git = 1;
} else if (!strcmp(reader.line, "version 2")) {
/*
* v2 smart http; do not consume version packet, which will
* be handled elsewhere.
*/
d->proto_git = 1;
} else {
die(_("invalid server response; got '%s'"), reader.line);
}
}
我不明白为什么它忽略了版本 1。
版本 Git 协议 v1 和版本 2 之间的差异是,
本文档介绍了 Git 有线协议第 2 版的规范。协议 v2 将在以下方面改进 v1:
单个服务将支持多个命令,而不是多个服务名称
随着功能被移动到协议的自己的部分,可以轻松扩展,不再隐藏在 NUL 字节后面并受 pkt 行大小的限制
分离出隐藏在 NUL 字节后面的其他信息(例如,作为功能的代理字符串和可以使用 ls-refs 请求的 symrefs)
除非明确要求,否则将省略参考广告
ls-refs 命令显式请求一些 refs
设计时考虑到了 http 和 stateless-rpc。有了清晰的刷新语义,http 远程助手可以简单地充当代理
在协议 v2 中,通信是面向命令的。首次联系服务器时,将公布功能列表。其中一些功能将是客户端可以请求执行的命令。命令完成后,客户端可以重用连接并请求执行其他命令。
Git 文档中有关协议 v2 的更多信息, https://git-scm.com/docs/protocol-v2
没有“Git 协议 v1”。有零版本,这是第一个版本(如果需要,您可以 调用 “v1”,但 Git 不需要);然后是version 2,也就是第二个版本。所以有效的选择是 v0 和 v2。
“协议 v1”在 commit aa9bab2(Gti 2.16.0,2017 年 10 月)中引入
Protocol version 1 is simply the original and current protocol (what I'm calling version 0) with the addition of a single packet line, which precedes the ref advertisement, indicating the protocol version being spoken.
由于 v2 改进了 v1,因此不再直接支持 v1:它是 v0 或 v2。
关于 v2,在 Git 2.34(2021 年第 4 季度)中,http-backend 已更新为在对方请求时自动启用协议 v2,利用 CGI 接口。
参见 commit 1b421e7, commit 2834a72, commit 295d81b, commit ff6a37c, commit 2614698 (10 Sep 2021) by Jeff King (peff
)。
(由 Junio C Hamano -- gitster
-- in commit cabb41d 合并,2021 年 9 月 23 日)
docs/http-backend
: mention v2 protocolSigned-off-by: Jeff King
Historically there was a little bit of configuration needed at the webserver level in order to get the client's v2 protocol probes to Git.
But when we introduced the v2 protocol, we never documented these.As of the previous commit, this should mostly work out of the box without any explicit configuration.
But it's worth documenting this to make it clear how we expect it to work, especially in the face of webservers which don't provide all headers over the CGI interface.
Or anybody who runs across this documentation but has an older version of Git (or used to have an older version, and wonders why they still have aSetEnvIf
line in their Apache config and whether it's still necessary).
git http-backend
现在包含在其 man page 中:
taking advantage of the CGI interface, It also supports Git's more-efficient "v2" protocol if properly configured;
git http-backend
现在包含在其 man page 中:
# This is not strictly necessary using Apache and a modern version of # git-http-backend, as the webserver will pass along the header in the # environment as HTTP_GIT_PROTOCOL, and http-backend will copy that into # GIT_PROTOCOL. But you may need this line (or something similar if you # are using a different webserver), or if you want to support older Git # versions that did not do that copying. # # Having the webserver set up GIT_PROTOCOL is perfectly fine even with # modern versions (and will take precedence over HTTP_GIT_PROTOCOL, # which means it can be used to override the client's request). SetEnvIf Git-Protocol ".*" GIT_PROTOCOL=[=10=]
git http-backend
现在包含在其 man page 中:
Clients may probe for optional protocol capabilities (like the v2 protocol) using the
Git-Protocol
HTTP header. In order to support these, the contents of that header must appear in theGIT_PROTOCOL
environment variable. Most webservers will pass this header to the CGI via theHTTP_GIT_PROTOCOL
variable, andgit-http-backend
will automatically copy that toGIT_PROTOCOL
. However, some webservers may be more selective about which headers they'll pass, in which case they need to be configured explicitly (see the mention ofGit-Protocol
in the Apache config from the earlier EXAMPLES section).
git -c protocol.version=1 clone...
曾经在 t/interop/i5700-protocol-transition.sh
中工作,但仅适用于 Got 2.0.0,而不是之后。
那是因为它是互操作测试:
This directory has interoperability tests for git.
Each script is similar to the normal test scripts found int/
, but with the added twist that two special versions of git, "git.a
" and "git.b
", are available in thePATH
.
Individual tests can then check the interaction between the two versions.
所以 protocol.version=1
只适用于 Git 2.0.0。不是之前也不是之后。