码云即将支持 Git v2 Protocol

原创
2018/05/23 15:53
阅读数 3.7K

美国当地时间 5月18日 Google 开发者发布了一篇博客 Introducing Git protocol version 2 宣布了 Git v2 Protocol,v2 协议又叫做 Git Wire Protocol,新协议旨在改进 Git 的传输过程。

通常情况下,Git 传输协议 (v1 smart protocol)是非常高效的,但是当一个存储库体积巨大或者引用(分支)数目巨多时,这个结论不再有效,此时用户体验将变得非常差。

在 v1 协议中,任何请求都是从发现引用开始,比如 git clone https://host/repo.git 的第一步就是 GET /repo.git/info/refs?service=git-upload-pack,这个时候,服务器要列出所有的引用,如果存在一万个引用就意味着一万个引用都需要解析然后传输,而基于 Pull-Request 模型的开发流程这种情况将更加突出(每一次创建一个 PR 相当于创建若干引用),这就给 Git 的传输带来了很大的压力,用户也需要花费更长的时间等待。

在 v1 协议中,git 传输的扩展性非常差,git 智能协议实际上并不智能,智能传输实际上仅仅是两组命令输入输出的交换,输入输出仅仅是计算好的数据,并且没有考虑到扩展性。以 HTTP 浅表克隆为例 , git 需要协商需要的 commit 深度,由于 HTTP 协议是无状态协议,请求流程是 Request-Response ,因此在第一个 HTTP post 请求时,fetch-pack 需要输出 depth 的值,然后等待 upload-pack 计算此上限 commit id,fetch-pack 再次发送请求告知 upload-pack 需要的上限 commitid,在 v1 协议中只能别扭的实现此功能,Http Git 服务器开发者也需要注意此处需要及时的让 git-upload-pack 退出,否则会出现竞争长时间挂起。

而在 v2 协议中,虽然还是两组命令输入输出的交换,但这些输入输出中还可以携带要执行的命令。此时的浅表克隆可以以命令加参数的形式通知服务器,服务器上相应的命令直接计算当前分支最新的 commit 以及 deepen 值即可,简化了传输流程。

这里有一个 v1 与 v2 的简短比较

细节 Git Smart Protocol Git Wire Protocol
协议细节 一对命令的输入输出交换 一组命令的输入输出交换
git-fetch-pack/git-upload-pack ls-refs(get refs),fetch(fetch pack)
git-send-pack/git-upload-pack push 暂未利用 Wire Protocol
数据格式 pktline pktline

查看协议内容:protocol-v2 我们可以发现主要是 Capability AdvertisementCommand RequestCapabilities 能够更好的指定 capabilities,特定的 command

为了方便读者直观了解,这里有两个 Gist 片段 https://gitee.com/ipvb/codes/y1b4ew3vqfgom5298iznh69 分别是 v1 和 v2 传输协议的抓包分析。

由于 Git 2.18 还未发布,用户想直接用上 v2 功能得直接从源码构建 Git。在 Git 的 pu 分支,我们还发现协议相对于 master 分支有所修改,主要是增加了 filter 这个功能主要是为了支持部分检出,类似与 Git GVFS,这种功能将极大的优化巨型存储库的访问,这正是 v2 扩展性好的体格体现。

If the 'filter' feature is advertised, the following argument can be
included in the client's request:

    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.

v2 与 v1 协议最大的区别在于,v1 协议是基于服务 (service) 的,服务功能单一,fetch-pack ---> upload-packfetchsend-pack ---> receive-packpush,而 v2 协议则变成了可以执行多个命令,这与 svn 协议又有了相似之处。不同类型的版本控制系统也在互相吸取经验。

Wire Protocol 协议的内容可以在这里找到。

码云的进展

笔者在了解到 v2 协议发布后,花了几天实现了对 v2 协议的兼容。

HTTP 协议需要检测请求头中是否有 Git-Protocol 然后 GET 请求时不再输出 # service=git-upload-pack 这样的标志,添加环境变量 GIT_PROTOCOL=version=2 去执行 git-upload-pack/git-receive-pack.

SSH 协议支持 SetEnv 修改环境变量,所以只要接受客户端的 SetEnv 请求,然后和 HTTP 一样即可,SSH 没有 # service=xx 因此也没有那一不需要修改。

Git 协议需要重新解析数据头,判断是否存在 version=2,类似头部 003egit-upload-pack /project.git\0host=myserver.com\0\0version=2\0

码云架构早已经变成了分布式的, 我们拥有统一的 Git 传输服务 git-srv 有 HTTP/SSH/GIT 适配,在与 git-srv 协商时,增加一个 version 字段,然后 git-srv 在启动 git 命令时,如果发现不为空就设置环境变量即可。

目前包括 Git SSH HTTP 协议都已经做到了兼容 v2 协议。但由于 Git 2.18 还未释放,协议也在改进,这些x新功能也需要一些时日才能上线。

Name Protocol Tech v2 Status description
Basalt Sshd SSH C++,libssh OK backend git-srv
Brzo HTTP C++, asio OK backend git-srv
Boite Git C++,asio OK backend git-srv
Git-diamond Git C++,asio OK Internal Transfer Server
Basalt Sshd (Go) SSH Go OK Distributed, backend git-srv
Bsshd SSH Go OK Single Machine
Brzox HTTP Go OK backend git-srv
Brack HTTP Go OK Single Machine

Go 的单机版主要是为一些小企业优化。

如何使用

用户需要从源码编译 git . 然后找到一个支持 v2 的服务器,目前主流的 Git 托管平台都暂不支持(除了 Google 的),官方的 git-http-backend 支持,这里有一个笔者贡献的 git-http-backend 已经支持:https://github.com/asim/git-http-backend。 需要注意服务器上的 git 也需要是最新版,否则无法使用。

git -c protocol.version=2 clone http://domian/repo.git

为了简化操作,可以在 .zshrc 或者 .bashrc 中新建别名:

alias git2='/path/to/git/installdir/bin/git -c protocol.version=2'

检测远程服务器是否支持 v2

GIT_TRACE_PACKET=1 git -c protocol.version=2 ls-remote

大家有更多的疑问可以去 https://gitee.com/oscstudio/git/issues 打开一个 Issues。

彩蛋:https://gitee.com/oscstudio/git 的 HTTP2 分支支持 HTTP2,需要服务器支持。

展开阅读全文
打赏
4
1 收藏
分享
加载中

引用来自“Fedo”的评论

这与 svn 协议又有了相似指出。😬 指出
谢谢,已修改。
2018/05/30 15:05
回复
举报
这与 svn 协议又有了相似指出。😬 指出
2018/05/30 12:43
回复
举报
厉害了我的薯
2018/05/25 19:02
回复
举报
好厉害,必须顶一下!
好长时间没有研究 git 协议了,现在已经落伍了。
2018/05/25 09:30
回复
举报

引用来自“Tom-Lin”的评论

厉害了,我的云
厉害了这评论说出了我想说的 哈哈
2018/05/25 09:22
回复
举报
6666
2018/05/25 08:45
回复
举报
厉害了,我的云
2018/05/25 08:38
回复
举报
厉害了我的码
2018/05/25 08:36
回复
举报
2018/05/24 18:29
回复
举报
foy
6666666
2018/05/24 11:37
回复
举报
更多评论
打赏
12 评论
1 收藏
4
分享
返回顶部
顶部