两个半月前,Google 开发者宣布了 Git Wire Protocol,即 Git v2 协议,Git Wire Protocol 协议改进了 Git 的传输过程,增长了可扩展性。关于协议的背景和细节介绍,你们能够去 《码云即将支持 Git v2 Protocol》 了解。git
两个多月过去了,咱们能够大声的告诉你们,码云目前已经支持 Git Wire Protocol。github
码云的 Git SSH 服务器并非 OpenSSH,而是基于 libssh 开发的一个服务,叫 Basalt Sshd。用户能够经过使用命令:shell
ssh -Tvvv git@gitee.com
在命令输出里面能够找到相似下面的字符串。后端
debug1: Remote protocol version 2.0, remote software version Basalt-1.2
对码云比较了解的朋友应该知道,码云目前已经彻底改形成分布式了,而 Basalt 是码云的 SSH 服务,它须要与存储机器上的 git-srv
创建链接,不管是 fetch
仍是 push
,码云都是经过启动 git 命令实现的,这样的好处是可以享受 git 改进带来的性能优点和增长的新功能。这一点,不管是 libgit2 仍是 JGIT 都并不容易作到的。bash
分析了码云平台 Git 传输的架构,那么就能够知道如何实现对 Git Wire Protocol 的支持,首先得让 Basalt
接受环境变量,而后得传递给 git-srv
,git-srv
在启动的时候设置 git 命令的环境变量便可,很简单吗,没有一点难度。固然须要等待 git 2.18 的发布,码云在计划支持 Git Wire Protocol 就等了一段时间。服务器
在 libssh 的 channel_env_request_function
callback 中就能够接受环境变量,这里就能够得知请求是不是 v2 的,在 git-srv 中,咱们在传输数据以前有个 Handshake
阶段,在 Handshake
数据包中增长一个字段便可。网络
等到 git 2.18 发布后,咱们将全部后端服务器上的 Git 升级到 2.18,而后升级全部的 git-srv
,最后把 Basalt 升级了,而后就支持 Git Wire Protocol 了。架构
咱们使用 git-dist 升级的 git/cmake。ssh
# update git bash <(curl -fsSL https://gitee.com/oscstudio/git-dist/raw/master/git-dist.sh)
# update cmake bash <(curl -fsSL https://gitee.com/oscstudio/git-dist/raw/master/cmake.sh)
以上是 SSH,那么 HTTP,GIT 呢?curl
在码云的设计中,HTTP 也应当直接与 git-srv
通信,而在 Gitlab 中,提供 Git HTTP 功能的是 grack,但 Gitlab 都有几年没有维护 Grack 了,他们已经使用 gitaly
了,虽然码云也将彻底去除 grack,但因为各类各样的缘由,目前依然使用 grack 提供 Git HTTP 访问。为了让开发者及早的体验 Git Wire Protocol,笔者一个非 Ruby 开发人员不情愿的改进了 Grack: https://gitee.com/oscstudio/grack 。若是哪一天你使用 HTTP 体验了 Git Wire Protocol,那就说明咱们更新了。
git://
协议没有验证机制,为了不恶意请求,咱们也就没有开放 git://
协议,但咱们内部同步使用了 git://
协议,而且也在第一时间支持了 Git Wire Protocol
.
咱们能够设置 git config
,使默认的传输使用 v2。
针对存储库的设置:git config protocol.version=2
针对全局设置: git config --global protocol.version=2
git 实际上可使用 -c
去强制指定一些设置,因此可使用 git -c protocol.version=2 clone url
这样的格式去使用 v2 协议去克隆或者操做 git 存储库。
若是已经码云上已经有存储库了,可使用 ls-remote
查看 Git Wire Protocol 细节。
GIT_TRACE=1 GIT_TRACE_PACKET=1 git -c protocol.version=2 ls-remote
这是 oscstudio/grack 的输出:
15:52:27.525041 git.c:415 trace: built-in: git ls-remote 15:52:27.525181 run-command.c:637 trace: run_command: unset GIT_CONFIG_PARAMETERS GIT_PREFIX; GIT_PROTOCOL=version=2 ssh -o SendEnv=GIT_PROTOCOL git@gitee.com 'git-upload-pack '\''oscstudio/grack.git'\''' 15:52:27.941054 pkt-line.c:80 packet: git< version 2 15:52:27.941085 pkt-line.c:80 packet: git< agent=git/2.18.0 15:52:27.941091 pkt-line.c:80 packet: git< ls-refs 15:52:27.941096 pkt-line.c:80 packet: git< fetch=shallow 15:52:27.941101 pkt-line.c:80 packet: git< server-option 15:52:27.941107 pkt-line.c:80 packet: git< 0000 15:52:27.941113 pkt-line.c:80 packet: git> command=ls-refs 15:52:27.941127 pkt-line.c:80 packet: git> agent=git/2.18.0 15:52:27.941133 pkt-line.c:80 packet: git> 0001 15:52:27.941150 pkt-line.c:80 packet: git> peel 15:52:27.941156 pkt-line.c:80 packet: git> symrefs 15:52:27.941160 pkt-line.c:80 packet: git> 0000 15:52:27.967209 pkt-line.c:80 packet: git< 715a91a2b22de70a78ba7e0cda2e36a65885184b HEAD symref-target:refs/heads/master 15:52:27.989776 pkt-line.c:80 packet: git< 642cbc5f73d6eb1947f3120e48cd8c401dd66961 refs/fetches/wenjiachengy/wire_debug 15:52:27.989817 pkt-line.c:80 packet: git< d77535c7d2892fede73f957d7041e66f6196c1da refs/heads/dev 15:52:27.989829 pkt-line.c:80 packet: git< 715a91a2b22de70a78ba7e0cda2e36a65885184b refs/heads/master 15:52:27.989866 pkt-line.c:80 packet: git< 94fafdc22aecf4561a7a94bd76a97336ab845654 refs/heads/stderr 15:52:27.989883 pkt-line.c:80 packet: git< 715a91a2b22de70a78ba7e0cda2e36a65885184b refs/heads/wire 15:52:28.005575 pkt-line.c:80 packet: git< 9795dec8d00c9c402ebf3db9e9d0f637d4f9dd6f refs/heads/wire_debug 15:52:28.033921 pkt-line.c:80 packet: git< 34eb1b8d0be0398044b45660effb9cfa21f2f324 refs/pull/1/MERGE 15:52:28.033973 pkt-line.c:80 packet: git< 36053e3bed3c355b0f184138df4d5e97a66a529a refs/tags/v0.1 peeled:623bc4f455bca96a6431e20babb436974417a5fc 15:52:28.033992 pkt-line.c:80 packet: git< 30d8963cefb373b9ccc10caebc80859f7e32ca28 refs/tags/v0.2 peeled:5295cd7b31a85197949c9f348210965907c7214b 15:52:28.034013 pkt-line.c:80 packet: git< eac92e5bd234f6a42db3f63a55c6909311ac998d refs/tags/v1.0.0 15:52:28.034032 pkt-line.c:80 packet: git< a6c716e02da853e811b96e6a6c37e21ec893a06a refs/tags/v2.0.0 15:52:28.034047 pkt-line.c:80 packet: git< 0000 15:52:28.034060 pkt-line.c:80 packet: git> 0000 From git@gitee.com:oscstudio/grack.git 715a91a2b22de70a78ba7e0cda2e36a65885184b HEAD 642cbc5f73d6eb1947f3120e48cd8c401dd66961 refs/fetches/wenjiachengy/wire_debug d77535c7d2892fede73f957d7041e66f6196c1da refs/heads/dev 715a91a2b22de70a78ba7e0cda2e36a65885184b refs/heads/master 94fafdc22aecf4561a7a94bd76a97336ab845654 refs/heads/stderr 715a91a2b22de70a78ba7e0cda2e36a65885184b refs/heads/wire 9795dec8d00c9c402ebf3db9e9d0f637d4f9dd6f refs/heads/wire_debug 34eb1b8d0be0398044b45660effb9cfa21f2f324 refs/pull/1/MERGE 36053e3bed3c355b0f184138df4d5e97a66a529a refs/tags/v0.1 623bc4f455bca96a6431e20babb436974417a5fc refs/tags/v0.1^{} 30d8963cefb373b9ccc10caebc80859f7e32ca28 refs/tags/v0.2 5295cd7b31a85197949c9f348210965907c7214b refs/tags/v0.2^{} eac92e5bd234f6a42db3f63a55c6909311ac998d refs/tags/v1.0.0 a6c716e02da853e811b96e6a6c37e21ec893a06a refs/tags/v2.0.0
场景 | 好处 |
---|---|
clone | 浅表克隆之类的操做被简化了 |
fetch | 可以过滤掉不须要的引用,意味着只须要关系本身的分支 |
push | 暂未使用 |
当你在码云上有存储库,而且存储库分支比较多的时候,你能够分别使用以下命令观察:
GIT_TRACE=1 GIT_TRACE_PACKET=1 git -c protocol.version=2 fetch origin master
GIT_TRACE=1 GIT_TRACE_PACKET=1 git fetch origin master
能够发现 v1 协议须要去查看全部的引用,而 Wire 并不须要这样作。固然 Wire 才推出不久,用户体验上改进还不是很明显,但随着 git 其余功能与 wire 传输协议的整合,用户在使用 git 的感觉也将愈来愈好。
Google 云平台最开始支持 Git Wire Protocol,如今码云也支持了,下面是厂商支持列表:
平台 | 是否支持 Git v2 |
---|---|
Gitee | 支持 SSH/HTTP |
Github | 不支持 |
Gitlab | 在作,但 Gitlab.org 不支持 |
Bitbucket | 不支持 |
Gitea | 不支持,但有 Issue 讨论 |
Gogs | 不支持,但有 Issue 讨论 |
Coding | 不支持 |
Git V2 对于一些小型存储库并不明显,但对于浅表克隆,海量分支的项目,v2 带来的改进很是明显,另外其扩展性对于 git 正在作的部分克隆(相似 Git VFS/GVFS)很是有利,随着项目规模的扩大,Git 这种分布式版本控制系统愈来愈力不从心,不断的出现 Git LFS, Git GVFS 也就是人们不断的探索。
不管是 SSH 仍是 HTTP,码云的基础设施团队都对其进行了大量的改进,好比目前的 Basalt libssh 已经升级到 0.8.1
,修复了 ED25519
HostKey 的支持,对于一些网络不稳定,或者特殊存储库克隆到 100% 时,出现 Broken Pipe
错误,咱们也已经修复。
若是诸位再次出现此错误,那就给咱们反馈,若是是咱们的错误那就说明可能尚未修复。
咱们还有提高了 git-srv
的稳定性。
对于 Basalt 而言,错误提示如今更加清晰,用户一眼就知道错误出如今哪里。好比克隆一个不存在的存储库提示以下:
除了这些改进,码云还有 Git LFS,SVN-SSH 等等功能即将上线,码云基础设施团队还实现了一个 Git VFS (aka GVFS) 的原型,你们有更好的想法和建议欢迎与码云开发者交流。