天天看點

Go Git:面向未來的代碼平台

2019杭州雲栖大會大咖有約,由阿裡巴巴·研發效能部·代碼基礎技術團隊負責人蔣鑫(Git項目貢獻者、《Git權威指南》作者)主講“Go Git:面向未來的代碼平台”。專題圍繞版本控制系統的曆史、現狀和未來,嘗試回答一個問題:未來的版本控制系統是什麼樣的?還會是Git麼? 精彩直播回放--9月25日下午“大咖有約”專場

以下為精彩視訊内容整理:

作為Git項目的貢獻者、本地化的國際協調者,主講人開場給大家奉獻了一個小竅門,和一個連結(開源電子書):

  • 一個讓你超越90%的Git使用者的小竅門:如何分析一個開發者在項目中的送出。例如檢視某個目錄之外的貢獻:
  1. log --author "Author" --no-merges --oneline -- ":(exclude)po/"

SVN是2000年誕生的,5年之後誕生的 Git 最終超越、替代了SVN。Git 已經快15歲了,目前為止仍然是使用者最喜愛的版本控制系統,那麼再過15年,Git會被什麼替代?

一、 未來——在火星上編碼

在電影裡,人類已經開始殖民火星。一個大膽的設想,未來人類會在火星上編碼!

光速作為難以突破的實體極限,從火星到地球,通訊有至少8 分鐘的延遲。在如此長的時延下,使用依賴中央伺服器的集中式版本控制工具,這幾乎是不可能實作的。由此推斷在火星上使用的版本控制系統需要有如下的特性:

  • 是分布式的,能夠本地克隆以及離線操作。
  • 建構一個火星版的CDN,也許是一個好主意。

二、過去——版本控制曆史發展脈絡

在Git誕生10周年時,Linus Torvalds說Git之是以能夠流行,主要原因不是Git速度快,或者它更安全,而是“politics”。

Go Git:面向未來的代碼平台

SVN就是一個典型的politically incorrect的版本控制工具。這裡的“政治”指的是:SVN不允許所有人向倉庫貢獻代碼,這是因為SVN如果向所有人開放倉庫的寫授權,代碼品質無法控制。

而Git是一個politically correct的版本控制工具。這是因為使用Git,使用者如果能夠讀到一個倉庫,就可以将其完整的克隆下來,然後在自己下載下傳的本地倉庫中送出代碼,并且通過各種手段分享給其他人。

2008年出現的GitHub之是以大獲成功, “political correctness”功不可沒。GitHub發明的“fork(派生)和pull request”的功能,讓協同更加簡單,使用者隻要點幾下滑鼠,就能完成代碼的分享。目前大多數代碼平台都拷貝了GitHub的這種協同模式。

但是GitHub的“fork + pull request”模式給使用者帶來新的苦惱,如何讓派生出來的倉庫和源倉庫保持同步?尤其在公司的内部環境下,使用者可信,派生帶來的同步成本使得使用者通常會舍棄GitHub的派生模式,轉而在一個倉庫下使用多分支的方式來協同,而這又帶來高昂的維護成本,管理混亂。

阿裡内部提供了一個集中式的解決方案,倉庫不需要派生,也不需要建立多分支進行協同。倉庫隻有一份,分支也僅有幾條,作為開發者像使用正常Git倉庫一樣進行push,當進行push時,會通過一層過濾器,過濾器的作用是把代碼直接變成一個代碼稽核任務,而不會在倉庫中建立任何的可見的多餘分支。

此外我們還做了一個配套的指令行工具:git-repo。這個工具,即可以針對單倉庫使用,也相容安卓的repo工具對多倉庫項目進行管理。(PS:問答環節一個同學問到多項目用配置檔案關聯的問題,可以用git-repo來解決。)阿裡巴巴開發的這個新穎的工作模式和git-repo将會在2019年年底開源。

未來版本控制系統,類似于阿裡巴巴的集中式代碼評審,将會成為主流。

三、 現在——大倉庫問題

2005年Linux kernel的代碼倉庫隻有不到100M,到目前為止Linux kernel的倉庫的代碼量已經接近4GB。Windows的代碼也放入Git倉庫裡,大概有300GB。如此大的倉庫将會遇到很多問題,有服務端的問題,也有用戶端的問題。問題的本質是Git本身的資料結構并不是常見的結構化資料,不是資料庫,而是一種半結構化資料,檢索速度相對比較慢。

Go Git:面向未來的代碼平台

Git已經做了很多的努力。比如:

  • 克隆一個倉庫,開始的一段時間會顯示一個進度,是在計算用戶端要接收的對象數,這時服務端正在計算客戶要擷取的送出範圍所包含的所有對象,這個計算的耗時比較長。Git的Bitmap功能就是針對這個問題的優化。
  • Git-graph是微軟貢獻給Git社群的一個新特性。因為在微軟的VSTS顯示送出曆史的界面中會畫出一棵樹圖,用來顯示送出與送出的關聯以及分支關系。實時渲染這樣一棵樹會很慢,于是微軟開發了輔助的資料結構git-graph。
  • Gerrit中的Reftable則是為了解決引用的快速查詢問題。

對于大倉庫,GC是一個老大難問題。每向倉庫進行一次push,倉庫裡就會有很多推送過去的松散對象,松散對象過多會導緻Git通路時的IO非常高,為此Git的解決辦法就是用gc指令将松散對象回收到一個一個的pack檔案裡。增量建立pack包,會出現越來越多的封包件,在索引一個對象時需要周遊每一個pack檔案,于是查找對象的時間複雜度就變成M*logN(M為封包件的個數,N為保檔案中的對象數)。而選擇用git gc完整壓縮隻生成一個大的pack,則會非常耗時,對于像微軟的300GB的代碼倉,簡直是不可能完成的任務。社群的一個解決方法是multi-index:為多個pack檔案建立multi-index索引,将查詢對象的時間複雜度降到O(logN)。

同時用戶端也有瓶頸。在面對300GB的倉庫時,使用者可能隻需要最新的送出,或者是部分目錄下的代碼,曆史的幾百個G的曆史資料不需要,那麼怎樣将其下載下傳下來?Git現有的工具有shallow clone(分層克隆)、sparse checkout(稀疏檢出)可以有選擇的檢出部分檔案、目錄。Git-LFS是GitHub開源的工具,解決的問題是将二進制資料不存放在倉庫裡而放在其他系統中,如阿裡雲的OSS存儲裡。GVFS是微軟開發的,用戶端隻克隆倉庫的中繼資料,按需下載下傳,這是解決上述問題的一個很好的方案。但是GVFS依賴于Windows作業系統、特殊的檔案系統。而Git正在研發的一個叫做partial clone的功能,會實作類似的按需檢出的功能。

斷點續傳也是使用者的一個痛點。是指在克隆一半的時候失敗了隻能從頭再開始,解決這個問題是很困難的,因為服務端是有狀态的,會計算所要擷取的對象并臨時打包。阿裡下一步會通過用戶端解決這個問題。

此外,Web IDE和建構加速領域裡都需要涉及克隆、重建倉庫中的代碼,很耗時。一個理想方案是zero time checkout、FUSE、分布式存儲。把倉庫裡的資料放在雲存儲裡,不需要檢出,不需要克隆,以解決這一類需要直接通路代碼倉庫的場景。

總之,針對大倉庫場景,Git有望在近幾年實作體驗的提升。

四、現在——多“分支”和響應延遲問題

很多Git使用者都可能遇到過這樣一個問題:在克隆一個分支(引用)非常多的倉庫時,往往挂起幾分鐘,在這幾分鐘裡得不到任何服務端的響應,好像是用戶端程序死掉了。這是因為Git 協定1.0(注意協定版本和Git版本概念不同),服務端要告知用戶端所有的引用,這個過程是靜默的,也就是為什麼複雜倉庫在連接配接階段非常耗時的原因。Git正在開發2.0版本的協定正是為了解決這個問題。

Go Git:面向未來的代碼平台

當使用Git Protocol 2.0時,想克隆哪個分支,服務端就會告知這個分支,而不是将所有的分支都傳回。此外,客戶可能更需要的一個功能是:當倉庫克隆下來之後,下次再同步時,希望可以查詢到從上次同步時倉庫的變化,以便增量下載下傳。這個功能可能通過類似reftable的功能來實作。

五、現在——其它問題

  • 安全性

    Git正在做從SHA1 到SHA256的遷移,當完成遷移之後,會發現倉庫的送出号為40位元組的十六進制數字,變成SHA256之後的64個位元組的十六進制數字。

  • Git的适用範圍

    Git的主要場景是針對代碼等文本檔案的版本控制。很多專業領域,如3D模組化,不能很好地進行版本控制。Git可通過 clean、smudge 過濾器、diff driver,來擴充版本控制的領域。

  • AI

    阿裡正在做AI方面的探索,主要針對在智能評審、智能搜尋、智能運維、品質、安全、提效等領域。

六、未來的代碼平台

未來的代碼平台:

1.有可能不是Git,但是會非常像Git。

2.是一個分布式的版本控制工具,可以克隆,可以在本地做送出。使用集中式的模式,允許任何人、在任何地點向大倉庫裡推送任何東西,并且通過結構化資料來提速,使大倉庫的性能變得更好。

3.當遠端克隆一個倉庫時,CDN可以提供幫助使倉庫克隆得更快。尤其像中美之間,由于實體、網絡差異沒辦法通路服務的情況下,CDN就會發揮相應的作用。

4.在很多領域,比如Web IDE領域,能夠實作代碼零耗時的擷取。

5.代碼智能化。