兩個半月前,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) 的原型,你們有更好的想法和建議歡迎與碼雲開發者交流。