Git代碼分支開發工作流程


本文的工作流程,有一個共同點:都采用"功能驅動式開發"(Feature-driven development,簡稱FDD)。

它指的是,需求是開發的起點,先有需求再有功能分支(feature branch)或者補丁分支(hotfix branch)。完成開發后,該分支就合並到主分支,然后被刪除。

Git的幾種開發流程

  • TrunkBased
  • GitFlow
  • Github flow
  • Gitlab flow
  • AoneFlow (阿里)

Git flow

gitflow

gitflow 大致如上圖所示,要分 master 和 develop 分支

主分支用於存放對外發布的版本,任何時候在這個分支拿到的,都是穩定的分布版;后者用於日常開發,存放最新的開發版。

其次,項目存在三種短期分支。

功能分支(feature branch)
補丁分支(hotfix branch)
預發分支(release branch)

一旦完成開發,它們就會被合並進develop或master,然后被刪除。

Git flow 優缺點

Git flow的優點是清晰可控,缺點是相對復雜,需要同時維護兩個長期分支。大多數工具都將master當作默認分支,可是開發是在develop分支進行的,這導致經常要切換分支,非常煩人。

更大問題在於,這個模式是基於"版本發布"的,目標是一段時間以后產出一個新版本。但是,很多網站項目是"持續發布",代碼一有變動,就部署一次。這時,master分支和develop分支的差別不大,沒必要維護兩個長期分支。

Github flow

Github flow 是Git flow的簡化版,專門配合"持續發布"。它是 Github.com 使用的工作流程。

Github flow

它只有一個長期分支,就是master

第一步:根據需求,從master拉出新分支,不區分功能分支或補丁分支。

第二步:新分支開發完成后,或者需要討論的時候,就向master發起一個pull request(簡稱PR)。

第三步:Pull Request既是一個通知,讓別人注意到你的請求,又是一種對話機制,大家一起評審和討論你的代碼。對話過程中,你還可以不斷提交代碼。

第四步:你的Pull Request被接受,合並進master,重新部署后,原來你拉出來的那個分支就被刪除。(先部署再合並也可。)
Github flow 優缺點

Github flow 的最大優點就是簡單,對於"持續發布"的產品,可以說是最合適的流程。

問題在於它的假設:master分支的更新與產品的發布是一致的。也就是說,master分支的最新代碼,默認就是當前的線上代碼。

可是,有些時候並非如此,代碼合並進入master分支,並不代表它就能立刻發布。比如,蘋果商店的APP提交審核以后,等一段時間才能上架。這時,如果還有新的代碼提交,master分支就會與剛發布的版本不一致。另一個例子是,有些公司有發布窗口,只有指定時間才能發布,這也會導致線上版本落后於master分支。

上面這種情況,只有master一個主分支就不夠用了。通常,你不得不在master分支以外,另外新建一個production分支跟蹤線上版本。

Gitlab flow

Gitlab flow 是 Git flow 與 Github flow 的綜合。它吸取了兩者的優點,既有適應不同開發環境的彈性,又有單一主分支的簡單和便利。它是 Gitlab.com 推薦的做法。

上游優先

Gitlab flow 的最大原則叫做"上游優先"(upsteam first),即只存在一個主分支master,它是所有其他分支的"上游"。只有上游分支采納的代碼變化,才能應用到其他分支。

Gitlab flow 分成兩種情況,適應不同的開發流程。

持續發布的項目

對於"持續發布"的項目,它建議在master分支以外,再建立不同的環境分支。比如,"開發環境"的分支是master,"預發環境"的分支是pre-production,"生產環境"的分支是production。

gitlab持續發布

開發分支是預發分支的"上游",預發分支又是生產分支的"上游"。代碼的變化,必須由"上游"向"下游"發展。比如,生產環境出現了bug,這時就要新建一個功能分支,先把它合並到master,確認沒有問題,再cherry-pick到pre-production,這一步也沒有問題,才進入production。

只有緊急情況,才允許跳過上游,直接合並到下游分支。

版本發布

對於"版本發布"的項目,建議的做法是每一個穩定版本,都要從master分支拉出一個分支,比如2-3-stable、2-4-stable等等。

gitlab版本發布

以后,只有修補bug,才允許將代碼合並到這些分支,並且此時要更新小版本號。

小結:項目主要是分版本發布的,然后有bug或功能會加新的分支來進行開發.

TrunkBased

研發團隊在名稱為 Trunk 的單一分支進行開發,當開發工作到一定階段的時候達到可發布條件后,切出Release分支進行發布,並且Release分支是不可以修改的僅僅做發布使用。大部分SVN用戶是基於本模型進行開發。
適合小團隊的模型,大家都直接在Trunk上進行開發.

TrunkBased 模式 是持續集成思想所崇尚的工作方式,它由單個主干分支和許多發布分支組成,每個發布分支在特定版本的提交點上從主干創建出來,用來進行上線部署和 Hotfix。在 TrunkBased 模式中,沒有顯性的特性分支。當然實際上 Git 的分布式特征天生允許每個人有本地分支,TrunkBased 也並非排斥短期的特性分支存在,只不過在說這種模式的時候,大家通常都不會明確強調它罷了。

雖然近年來有許多不錯的案例,但 TrunkBased 模式並沒有一統天下。它的缺點比較明顯,太多的團隊同時工作在主干上,到發布的時候就可能出現災難(尤其是多版本並行開發的情況)。彌補的措施是 FeatureToggle 以及頻繁的集成和足夠的測試覆蓋,這對開發團隊的能力提出了比較高的要求。目前 TrunkBased 模式主要用在不需要同時維護多個歷史版本的 SaaS 型項目,特別是經過微服務改造的各種小型服務上。

類似github flow 沒有 pull request

AloneFlow

在 AoneFlow 上你能看到許多其他分支模式的影子。它基本上兼顧了 TrunkBased 的“易於持續集成”和 GitFlow 的“易於管理需求”特點,同時規避掉 GitFlow 的那些繁文縟節。

AoneFlow 只使用三種分支類型:主干分支、特性分支、發布分支,以及三條基本規則。

規則一,開始工作前,從主干創建特性分支。

AoneFlow 的特性分支基本借鑒 GitFlow,沒有什么特別之處。每當開始一件新的工作項(比如新的功能或是待解決的問題)的時候,從代表最新已發布版本的主干上創建一個通常以feature/前綴命名的特性分支,然后在這個分支上提交代碼修改。也就是說,每個工作項(可以是一個人完成,或是多個人協作完成)對應一個特性分支,所有的修改都不允許直接提交到主干。
aoneflow-1

規則二,通過合並特性分支,形成發布分支。

AoneFlow 的發布分支設計十分巧妙,可謂整個體系的精髓。GitFlow 先將已經完成的特性分支合並回公共主線(即開發分支),然后從公共主線拉出發布分支。TrunkBased 同樣是等所有需要的特性都在主干分支上開發完成,然后從主干分支的特定位置拉出發布分支。而 AoneFlow 的思路是,從主干上拉出一條新分支,將所有本次要集成或發布的特性分支依次合並過去,從而得到發布分支。發布分支通常以release/前綴命名。
aoneflow-2

這條規則很簡單,不過實際的玩法就相當豐富了。

首先,發布分支的用途可以很靈活。基礎玩法是將每條發布分支與具體的環境相對應,比如release/test分支對應部署測試環境,release/prod分支對應線上正式環境等等,並與流水線工具相結合,串聯各個環境上的代碼質量掃描和自動化測試關卡,將產出的部署包直接發布到相應環境上。進階點的玩法是將一個發布分支對應多個環境,比如把灰度發布和正式發布串在一起,中間加上人工驗收的步驟。高級的玩法呢,要是按迭代計划來關聯特性分支,創建出以迭代演進的固定發布分支,再把一系列環境都串在這個發布分支的流水線上,就有點經典持續集成流水線的味道了。再或者做一個將所有特性分支都關聯在一起的發布分支,專門用於對所有提交做集成測試,就玩出了 TrunkBased 的效果。當然,這些花哨的高級玩法是我臆想的,阿里的發布分支一般都還是比較中規中矩。

其次,發布分支的特性組成是動態的,調整起來特別容易。在一些市場瞬息萬變的互聯網企業,以及采用“敏捷運作”的乙方企業經常會遇到這種情況,已經完成就等待上線的需求,隨時可能由於市場策略調整或者甲方的一個臨時決定,其中某個功能忽然要求延遲發布或者干脆不要了。再或者是某個特性在上線前發現存在嚴重的開發問題,需要排除。按往常的做法,這時候就要來手工“剔代碼”了,將已經合並到開發分支或者主干分支的相關提交一個個剔除出去,做過的同學都知道很麻煩。在 AoneFlow 的模式下,重建發布分支只是分分鍾的事,將原本的發布分支刪掉,從主干拉出新的同名發布分支,再把需要保留的各特性分支合並過來就搞定。這一系列動作能夠在很大程度上實現自動化,而且不會在倉庫留下一堆剔除代碼的記錄,干凈無污染。

此外,發布分支之間是松耦合的,這樣就可以有多個集成環境分別進行不同的特性組合的集成測試,也能方便的管理各個特性進入到不同環境上部署的時機。松耦合並不代表沒有相關性,由於測試環境、集成環境、預發布環境、灰度環境和線上正式環境等發布流程通常是順序進行的,在流程上可以要求只有通過前一環境驗證的特性,才能傳遞到下一個環境做部署,形成漏斗形的特性發布流。阿里有統一平台來自動化完成特性組合在發布分支間的遷移,在下面講工具的部分里會再介紹。

規則三,發布到線上正式環境后,合並相應的發布分支到主干,在主干添加標簽,同時刪除該發布分支關聯的特性分支。

當一條發布分支上的流水線完成了一次線上正式環境的部署,就意味着相應的功能真正的發布了,此時應該將這條發布分支合並到主干。為了避免在代碼倉庫里堆積大量歷史上的特性分支,還應該清理掉已經上線部分特性分支。與 GitFlow 相似,主干分支上的最新版本始終與線上版本一致,如果要回溯歷史版本,只需在主干分支上找到相應的版本標簽即可。

aoneflow-3

除了基本規則,還有一些實際操作中不成文的技巧。比如上線后的 Hotfix,正常的處理方法應該是,創建一條新的發布分支,對應線上環境(相當於 Hotfix 分支),同時為這個分支創建臨時流水線,以保障必要的發布前檢查和冒煙測試能夠自動執行。但其實還有一種簡便方法是,將線上正式環境對應的發布分支上關聯的特性分支全部清退掉,在這個發布分支上直接進行修改,改完利用現成的流水線自動發布。如果非得修一個歷史版本的 Bug 怎么辦呢?那就老老實實的在主干分支找到版本標簽位置,然后從那個位置創建 Hotfix 分支吧,不過由於阿里的產品大多是線上 SaaS 業務,這樣的場景並不多見。

Aone flow 其他規范

在 AoneFlow 的流程中,每次重建發布分支的時候都會重新合並然后編譯代碼,產生新的部署包。然而,即使代碼的內容是一樣的,如果工程中依賴了一些會改變的第三方軟件包,依然可能導致打包出的產品行為不完全一致。因此,在阿里的代碼規約中就明確地指出了,用於線上發布的代碼,不可以使用包含“SNAPSHOT 版本”(即未正式發布版本)的依賴包,從而確保每次構建出的產物都是一致的。

在阿里內部,使用 AoneFlow 流程的團隊基本上不用自己運行 Git 來處理分支的事情,而是由阿里巴巴集團內部名叫 Aone 的協同研發平台(以下簡稱平台)接管。

References


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM