新一代高效Git协同模型AGit-Flow详解
?
?
【以下為分享實錄,有刪節(jié)】
Git工作流概述及AGit-Flow的優(yōu)勢
目前,Git已成為源代碼管理的標準和基礎(chǔ)設(shè)施?!盀槭裁碐it能這么成功”?Git的創(chuàng)建者Linux在Git十周年的一次采訪中,道出了其中的奧秘:
The big thing about distributed source control is that it makes one of the main issues with SCM’s go away – the politics around “who can make changes.”
他認為Git能成功最關(guān)鍵的不是因為它更快、更安全,也不是因為Git是分布式的,而是解決了“到底誰能夠貢獻代碼”這個問題。傳統(tǒng)的集中式版本控制系統(tǒng)只能針對核心用戶開放寫授權(quán),長期來看這對項目做大、做強是不利的。而Git改變了傳統(tǒng)版本控制系統(tǒng)不能夠讓跟多開發(fā)者貢獻代碼這個頑疾,讓“只讀用戶”也可以通過“代碼評審”的方式參與到項目開發(fā)中。
當(dāng)前業(yè)界有兩種最常用Git 工作流:GitHub和Gerrit。他們都具備倉庫的授權(quán)模型簡單,只讀用戶可參與代碼貢獻的特點。
?
?
如上圖所示,我對這兩種GIT工作流做了優(yōu)劣勢分析: ** 代碼評審模式不同:** GitHub 的代碼評審稱為 “pull request”,每個特性改動生成一次代碼評審。 Gerrit 的代碼評審稱為 “Change”,每個提交生都會生成一個“變更單”,這個變更單就是一次代碼評審。
工作流類型不同: GitHub 的工作流屬于分布式,當(dāng)開發(fā)者需要參與項目的時候,雖然沒有“寫”的權(quán)限,但是可以通過“Fork”的方式創(chuàng)建一個個人倉庫(派生倉庫),他就可以在這個派生倉庫中去創(chuàng)建代碼分支,創(chuàng)建pull request。GitHub 底層采用的是原生的 Git(即 CGit)。
Gerrit 的工作流是集中式,所有用戶工作在統(tǒng)一管控的集中式倉庫中。Gerrit 要求用戶在本地克隆倉庫中安裝一個 “commit-msg” 鉤子,以便在生成的提交中插入唯一的“Change-Id”,向服務(wù)器推送要使用特殊的 git push 命令。Gerrit 采用的是 JGit(Java 的 Git 實現(xiàn))。
**各自優(yōu)勢: ** GitHub簡單易用,使用標準 Git 命令即可完成代碼貢獻;對派生倉擁有完全控制力,不受上游項目影響;可以創(chuàng)建跨項目的開源社區(qū),全球開發(fā)者大協(xié)同,這也是GIT可以形成全球最大的開源社區(qū)的原因之一。
Gerrit 因為采用集中式的工作流,管理員可以對項目進行嚴格管控,可以嚴格控制誰可以訪問倉庫,誰可以對我的倉庫做貢獻。Gerrit另外一個優(yōu)勢是可以實現(xiàn)多倉庫項目管理。我們知道“Android”項目具有1000多個倉庫,就是使用Gerrit進行管理的,很難想象如何使用GitHub來管理Android的1000多個倉庫。
各自劣勢: 正如前面所說GitHub很難管理類似 Android 的多倉庫項目。另外因為GitHub 使用派生倉庫的工作模式,會產(chǎn)生服務(wù)端數(shù)據(jù)冗余的問題。
Gerrit 需要集中管控,由管理員負責(zé)創(chuàng)建項目,而普通用戶不能創(chuàng)建項目,這就使得一個 Gerrit 實例通常只管理一個項目或一個組織內(nèi)的項目,難以在項目之間形成代碼復(fù)用,也很難匯集跨項目的開發(fā)者組成開發(fā)者社區(qū)。
通過對GitHub和Gerrit等Git工作流的調(diào)研和學(xué)習(xí),我們“取長補短”創(chuàng)建了阿里巴巴的Git工作流,即AGit-Flow。
?
在阿里巴巴,我們喜歡 pull request、CGit,喜歡在命令行直接創(chuàng)建代碼評審的集中式工作流,喜歡開放的開發(fā)者社區(qū)。我們不喜歡 “commit-msg” 鉤子方式關(guān)聯(lián)提交的代碼評審,我們不喜歡一個一個分散的代碼平臺。
我們還開發(fā)了配套的客戶端工具 “git-repo”,既能在單倉庫下工作,又支持類似 Android 的多倉庫項目協(xié)同。
在阿里巴巴,我們?nèi)绾问褂肁Git-Flow
下面給大家演示一下,在阿里巴巴內(nèi)部,我們是如何使用AGit-Flow工作的。
?
我們首先使用Git標準命令將倉庫克隆到本地,然后在本地倉庫內(nèi)開發(fā),創(chuàng)建提交。在工作區(qū)中執(zhí)行 git pr 命令,推送本地提交到服務(wù)器,服務(wù)器端會自動創(chuàng)建一個新的代碼評審,例如:pull request #123。團隊的代碼評審者就可以打開編號“123”的代碼評審提交評審意見。開發(fā)者根據(jù)評審意見,在本地工作區(qū)繼續(xù)開發(fā)、新增或修改提交。工作區(qū)中再次執(zhí)行 git pr 命令,推送本地提交到服務(wù)器。服務(wù)器發(fā)現(xiàn)目標分支上已經(jīng)存在來自同一用戶、同一本地分支的 pull request,因此用戶此次推送沒有創(chuàng)建新的 pull request,而是更新已經(jīng)存在的 pull request。
如果經(jīng)過多次修改,代碼依然不OK。代碼評審者也可以直接發(fā)起對評審代碼的修改,幫助原開發(fā)者更新 pull request。代碼評審者可以使用 git download 123 下載編號為 123 的 pull request 到本地倉庫,代碼修改完畢后,執(zhí)行 git pr --change 123 命令,將本地修改推送到服務(wù)端。服務(wù)端接收到代碼評審者的特殊 git push 命令,更新之前由開發(fā)者創(chuàng)建的 pull request。項目管理者通過點擊 pull request 評審界面的合并按鈕,將 pull request 合入 master 分支。master 分支被更新,同時關(guān)閉 pull request。
使用AGit-Flow工作流無需在服務(wù)器上創(chuàng)建新的分支,不需要給新加入的同學(xué)創(chuàng)建寫入權(quán)限,可以對所有開發(fā)者只分配讀取權(quán)限,然后通過創(chuàng)建代碼評審再合并到主干的方式更新主干代碼。這也是目前比較流行的主干研發(fā)模式。
目前大家可以通過云效代碼管理平臺(Codeup)來實現(xiàn)AGit-Flow工作流。
AGit-Flow實現(xiàn)原理
?
?
AGit-Flow是如何實現(xiàn)的呢? 首先客戶端使用特殊的 git push 命令向服務(wù)端發(fā)起代碼推送請求,觸發(fā) AGit-Flow 工作流。為什么說這個git push 命令特殊呢?因為它的目標分支是一個包含特殊的前綴 “refs/for/"的代碼分支,分支后面又跟了一個 “” 。這個“”用于區(qū)分本地分支名,不同開發(fā)者提交的代碼評審包含不同的“”,所以不會相互覆蓋。
我們還可以通過“-o”來傳遞不同的參數(shù),比如可以指定由誰來對我的代碼進行評審,我的代碼評審會關(guān)聯(lián)哪個“issue”。這些操作都可以通過“git push”命令完成,后來我們發(fā)現(xiàn)這個git push 命令比較復(fù)雜,于是我們封裝了一個命令行工具git-repo。目前git-repo已經(jīng)對外開源,大家可以免費使用。
接下來這個“Push”命令就會打入到服務(wù)端,服務(wù)器端會啟動一個進程“git-receive-pack”。(我們對服務(wù)器端的前端授權(quán)模塊做了一些修改,使其能夠識別這個特殊的git push 命令,允許只讀用戶也能“Push”)如上圖所示,“git-receive-pack”我做了星號標記,因為它是一個特殊的“git-receive-pack”。當(dāng)它發(fā)現(xiàn) push命令的目標是一個特殊的引用后,它不會走Git原來內(nèi)部的工作流,而是走“外部鉤子”。通過“外部鉤子”完成一些好玩的操作,比如創(chuàng)建代碼評審。
在今年(2020年)3月份,我們已經(jīng)把這個修改過的git-core貢獻給了Git社區(qū),目前正在評審中,后續(xù)Git新版本會包含這個新特性:proc-receive。此特性已經(jīng)歷經(jīng)15次迭代,從最初的服務(wù)端擴展到集合了服務(wù)端擴展和客戶端協(xié)議升級的完整解決方案。我們將這個技術(shù)開源,一方面繁榮了Git 生態(tài),讓更多人能從阿里巴巴的技術(shù)中獲益;另外一方面,阿里巴巴也得到了收益,我們的代碼貢獻得到了Git客戶端的支持, Git適配了我們新的玩法,讓包含阿里巴巴在內(nèi)的Git用戶得到了更好的體驗。
AGit-Flow實現(xiàn)的技術(shù)細節(jié)
為了解釋AGit-Flow實現(xiàn)的技術(shù)細節(jié),我們先來了解一下git push命令原有的實現(xiàn)方式。 
如上圖左側(cè)所示, git push命令包含兩部分信息,一個是被打成包的數(shù)據(jù),叫“packfile”;另一個是推送的命令,叫“commands”。 “packfile”和“commands”被推送到服務(wù)端后,“packfile”會走左側(cè)的路徑,首先進入“quarantine”中,進行“隔離”。 當(dāng)“commands”經(jīng)過“pre-receive” 鉤子檢查,認為用戶的權(quán)限OK、提交說明OK、提交修改的文件ok,“packfile”才會從隔離區(qū)釋放出來,進入對象庫(objects)。(如果 “pre-receive” 鉤子腳本失敗,則刪除隔離區(qū),并返回錯誤信息,終止推送命令的執(zhí)行。)
接下來“commands”會傳遞給內(nèi)置的 “execute_commands()” 函數(shù),實現(xiàn)分支的創(chuàng)建、更新、刪除等操作。然后通過“repor()”函數(shù)報告給客戶端,最后執(zhí)行 “post-receive”鉤子腳本,完成事件通知。
新鉤子,新生態(tài)。AGit-Flow 對 “git-receive-pack” 的源碼做了改動,新的流程如下圖所示:
?
?
當(dāng)客戶端執(zhí)行新的git push命令后,“packfile”的傳播路徑?jīng)]有改變,但是我們更改了"git-receive-pack"命令,增加了一個“過濾器”(圖中漏斗部分)。過濾器將 “commands” 分成兩組,一組是標準的Git命令(group1),一組是AGit-Flow特殊的命令(group2)。這兩組命令經(jīng)過“pre-receive” 鉤子檢查后,左側(cè)普通的命令(group1)會執(zhí)行Git內(nèi)置的 execute_commands 函數(shù),生成新的引用,進行分支的創(chuàng)建、更新等。右側(cè)這個特殊的命令會調(diào)用一個新的外部鉤子 “proc-receive” ,然后創(chuàng)建一個特殊的代碼評審引用,如“refs/pull/123/head”,并且可以用過特殊的Git命令將它下載到本地。
?
?
我們?yōu)镚it貢獻的這個新特性,由三部分組成。第一個部分就是“過濾器”,通過在服務(wù)端新增新配置變量 "receive.procReceiveRefs"來實現(xiàn)。只要定義了這個特殊的配置變量,當(dāng)客戶端使用git push命令推送的時候,Git就會根據(jù)配置變量去匹配,當(dāng)匹配到相應(yīng)的命令時,這個命令就會走特殊流程。這個配置變量屬于多值變量,例如阿里巴巴代碼平臺的設(shè)置是:
-
git config --add receive.procReceiveRefs refs/for
-
git config --add receive.procReceiveRefs refs/drafts
-
git config --add receive.procReceiveRefs refs/for-review
這三條配置變量對應(yīng)git pr的三種推送模式,會產(chǎn)生標準的pull request、草稿模式的pull request,或者一個代碼評審者想推送指定的pull request。
?
?
?
?
第二部分是proc-receive 鉤子。我們這個鉤子應(yīng)該說是Git中有史以來最復(fù)雜的一個鉤子,它可以和服務(wù)端(git-receive-pack)進行雙向通訊。首先服務(wù)端和鉤子會做“版本協(xié)商”,因為我們認為這個協(xié)議后續(xù)會升級,為了保證向后兼容,所以我們首先要協(xié)商一個版本。服務(wù)端告訴鉤子我是哪個版本,客戶端告訴鉤子我支持哪個版本,后面Git就可以用相應(yīng)的版本協(xié)議與鉤子進行通訊。服務(wù)端會用“pkt-line”編碼命令,這個命令是三段式的,包含老的ID,新的ID和需要更新的引用名稱。服務(wù)端會把命令和參數(shù)發(fā)送給鉤子。鉤子會對這些命令和參數(shù)進行處理,這些處理由開發(fā)者以API調(diào)用的方式實現(xiàn),然后將處理結(jié)果報告給鉤子。鉤子再把這個執(zhí)行結(jié)果以特殊的方式報告給服務(wù)端。
?
?
第三部分是可定制的客戶端狀態(tài)報告。在上圖右側(cè)部分,大家可以看到有一條虛線由“proc-receive” 鉤子指向“execute-commands”函數(shù),這個代表有些鉤子無法處理的命令會返回給“execute-commands”函數(shù)進行處理。當(dāng)“execute-commands”和“execute-commands”鉤子處理完全部命令后,會統(tǒng)一進行“report()”(報告)。我們這個“report()”相比于Gerrit有一個優(yōu)勢,能夠讓客戶端知道你沒有改成“refs/for”引用,而是改成了另外一個引用。此外,我們也考慮了向下兼容問題,讓老版本的Git,在遇到新版本的Git服務(wù)器的時候一樣可以收到報告信息。例如老版本的Git會認為你創(chuàng)建了“refs/for/master”;但是新版本的Git懂得擴展協(xié)議,可以識別出你創(chuàng)建了特殊的引用,比如知道你創(chuàng)建的不是“refs/for/master”而是“refs/pull/123”這樣的引用。
阿里巴巴開源的客戶端工具git-repo簡介
?
?
git-repo 是阿里巴巴開源的一款集中式工作流命令行工具,對原生 Git 命令做了封裝,簡化了使用 AGit-Flow 等集中式工作流時稍嫌繁瑣的 Git 命令。git-repo是使用Go語言開發(fā),運行時除 Git 外不依賴其他軟件,所有具有拆包即用的優(yōu)點。
git-repo 具有良好的兼容性,可以支持 AGit-Flow 兼容的代碼平臺以及 Gerrit。可以跨平臺,目前支持Linux、Mac、 windows系統(tǒng),其中Windows是Beta版本。除了具備 Android repo 的多倉庫管理能力外,還可以對單獨的代碼倉庫進行操作。
如何下載安裝git-repo呢?git-repo目前已經(jīng)開源到Git hub中,你可以訪問https://github.com/alibaba/git-repo-go/releases頁面下載合適的安裝包。然后將解壓縮后的 git-repo 文件移動到可執(zhí)行目錄中(如 Linux 下的 /usr/local/bin 目錄),即完成安裝。詳細的使用方法此處不再贅述,大家可以訪問git-repo主頁了解。
總結(jié):
AGit-Flow 是阿里巴巴研發(fā)的 Git 集中式協(xié)同協(xié)議,目前已經(jīng)在阿里巴巴集團內(nèi)部生根開花,在外部,通過云效代碼管理平臺提供支持。
AGit-Flow的核心組件已經(jīng)開源,將已經(jīng)成為Git的核心組件。
為了方便開發(fā)者操作,我們開發(fā)了git-repo命令行工具。git-repo使用 Go 語言開發(fā),具有拆包即用、跨平臺、兼容性好、可擴展等特點。git-repo已經(jīng)開源道Git hub社區(qū)大家可以進入產(chǎn)品主頁免費下載使用。
以上內(nèi)容整理自知憂的視頻分享《AGit-Flow:新一代高效Git協(xié)同模型》,歡迎大家加入云效開發(fā)者交流群(釘釘群號:34532418)觀看視頻回放,下載演講PPT。
【關(guān)于云效】
云效,企業(yè)級一站式DevOps平臺,源于阿里巴巴先進的研發(fā)理念和工程實踐,致力于成為數(shù)字企業(yè)的研發(fā)效能引擎!云效提供從“需求 ->開發(fā)->測試->發(fā)布->運維->運營”端到端的在線協(xié)同服務(wù)和研發(fā)工具,通過人工智能、云原生技術(shù)的應(yīng)用助力開發(fā)者提升研發(fā)效能,持續(xù)交付有效價值。
【云效官網(wǎng)】https://www.aliyun.com/product/yunxiao?channel=zhibo 【公測指南】https://developer.aliyun.com/article/756207 【申請公測】https://devops.aliyun.com 【學(xué)習(xí)路徑】https://help.aliyun.com/document_detail/153739.html 【開發(fā)者社區(qū)】https://developer.aliyun.com/group/yunxiao 【精彩活動】云效公測開啟 「產(chǎn)品體驗官」招募 https://www.aliyun.com/activity/yunxiao/Beta2020
?
?
?
?
歡迎掃碼加入云效開發(fā)者俱樂部(釘群:34532418)
原文鏈接
本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
總結(jié)
以上是生活随笔為你收集整理的新一代高效Git协同模型AGit-Flow详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 点触科技:构建实时计算和数据仓库解决方案
- 下一篇: 来,一起“八卦”一下数据湖