團隊如何選擇合適的Git分支策略?

2023-04-02 18:01:29

現代軟體開發過程中要實現高效的團隊共同作業,需要使用程式碼分支管理工具實現程式碼的共用、追溯、回滾及維護等功能。目前流行的程式碼管理工具,包括CVS,SVN,Git,Mercurial等。

相比CVS和SVN的集中管理,Git具有非常明顯的優勢,例如:去中心化的程式碼管理方式減少了開發者對中心伺服器的依賴,每個成員在本地都有一個完整的程式碼庫,在不聯網的情況下也能提交程式碼;不同於SVN中的每個分支具有獨立的程式碼,Git中的每一個分支只是指向當前版本的一個指標,Git的分支策略使建立和合並分支變得快捷靈活

從百度指數,也可以看到Git的優勢被越來越多的人所認可。

Git的優勢

  • Git 可以在本地進行提交以支援離線工作;
  • Git 可以在本地建立分支並且沒有名稱空間衝突的問題;
  • Git 可以讓提交通過 Pull Request 的方式進行,不需要所有的開發者都有主倉庫的寫許可權;
  • Git 在優化效能時選擇了合併分支作為主要的效能衡量指標,將合併分支變成了成本非常低的操作以鼓勵分支的使用;
  • Git 通過 SHA-1 雜湊來保證倉庫中資料的可靠性,通過 SHA-1 就可以對資料進行校驗,抵禦了來自攻擊者的惡意篡改;

Git作為分散式的程式碼管理工具,越來越多的團隊開始使用它並逐步替代集中式的SVN 或 TFVC,同時也面臨新的挑戰。

版本管理的挑戰

大家工作在同一個倉庫上,那麼彼此的程式碼共同作業必然帶來很多問題和挑戰,如下:

  1. 如何開始一個Feature的開發,而不影響別的Feature?
  2. 由於很容易建立新分支,分支多瞭如何管理,時間久了,如何知道每個分支是幹什麼的?
  3. 哪些分支已經合併回了主幹?
  4. 如何進行Release的管理?開始一個Release的時候如何凍結Feature, 如何在Prepare Release的時候,開發人員可以繼續開發新的功能?
  5. 線上程式碼出Bug了,如何快速修復?而且修復的程式碼要包含到開發人員的分支以及下一個Release?

大部分開發人員現在使用Git就只是用三個甚至兩個分支,一個是Master, 一個是Develop, 還有一個是基於Develop打得各種分支。這個在小專案規模的時候還勉強可以支撐,因為很多人做專案就只有一個Release, 但是人員一多,而且專案週期一長就會出現各種問題。

Git程式碼分支模型

在使用Git管理程式碼以及多人共同作業的開發模式下,一個團隊甚至一個公司對Git的使用有統一規範的工作流程尤為重要。
開發團隊遵循統一的規則執行功能開發,問題修復,分支合併,版本迭代及釋出等操作,可以使團隊合作變得平滑順暢,專案有序向前推進,我們把組織內這樣的工作流程(workflow)稱為Git程式碼分支管理模型

主流的git程式碼分支管理模型:

  • Git flow
  • GitHub flow
  • GitLab flow
  • TBD flow

1. Git flow


Git flow存在兩個長期的獨立分支:主分支master和開發分支develop,

  • 主分支: 用於版本釋出,主分支的每個版本都是質量穩定和功能齊全的釋出版。
  • 開發分支: 用於日常開發工作,存放最新的開發版程式碼。當開發分支的程式碼達到穩定狀態並可以釋出版本時,程式碼需要被合併到 master 分支,然後標記上對應的版本標籤(tag)。

如果需要開發新的功能或者解決程式碼中的問題,則建立輔助分支來解決問題,輔助分支常用於:

  • 功能開發(Feature),
  • 版本釋出(Release),
  • 問題修復(Hotfix),

在輔助分支上的工作完成後,輔助分支將被刪除。

Feature分支
目的是開發新模組或新功能以滿足客戶需求,從develop分支建立,開發結束後只需要合併回develop分支,並不需要合併回master主分支。

Release分支
是用於準備釋出的版本分支,從develop分支建立,建立時已經包含了釋出所需要的所有功能,所以在這個分支上不再開發新功能,僅對這個預釋出版本進行修復問題,建立檔案及其他與釋出相關的工作,一切就緒後將Release分支合併回master主分支並打上相應的版本號標籤(Tag),同時也合併回develop分支。
建立單獨的Release分支可以避免在不同釋出版本上的工作互相受影響,例如團隊A準備釋出版本1.0的同時,團隊B正在進行版本1.1的功能開發,二者相互獨立,不會互相影響。

Hotfix分支
通常用於緊急修復當前釋出的版本中出現的嚴重問題,從釋出版本的標籤或master主分支建立,問題修復後合併回master主分支並打上新的版本號標籤(Tag),同時也合併回develop分支或者正在進行中的Release分支。
建立單獨的Hotfix分支可以避免打斷正在進行中的各項開發工作,客戶也不需要等到下一個釋出週期才能拿到修復。

優點&缺點
Git flow需要同時維護兩個甚至更多分支,Hotfix分支從master建立,Release和Feature分支從develop建立,工作完成後又需要將程式碼合併回 develop 和 master。

在實際應用中,很多開發者會忘記合併回 develop 或者 master,並且各輔助分支之間互相獨立,如果從master上pull程式碼不夠及時,一方面可能造成某個分支長期使用已經過時或者錯誤的程式碼,另一方面如果與master相隔較遠,合併分支時可能會有大量程式碼衝突,往往需要花費很多時間來消除程式碼衝突,並且非常容易出錯,影響專案的持續整合。

Git flow的優點在於流程清晰,分支管理嚴格,適用於釋出週期比較長的「版本釋出」,釋出週期可能是幾周,幾個月,甚至更長時間。
由於保持兩個長期分支同步的開銷較大,所以Git flow並不適用於快速的「持續釋出」,ThoughtWorks還專門將Git flow列為不被推薦的技術,建議徹底停止使用。

綜合考慮了開發、測試、新功能開發、臨時需求、熱修復,理想很豐滿,現實很骨幹,這一套執行起來實在是太複雜了

2. GitHub flow

GitHub flow是由Scott Chacon於2011年提出的程式碼分支管理模型,這是GitHub官方推薦的開發流程,以快速部署為目標,目前大部分開源專案都遵循這一流程。

Github flow最大的特點是隻有一個長期分支,即主分支master,且主分支始終保持可釋出狀態。
從master上建立新分支進行功能開發、問題修復等,這些分支通過pull request將程式碼合併到master。為了保證主分支的程式碼質量,master的許可權只開放給一部分人。
Pull request是請求別人pull你的程式碼庫(repository),也就是把開發分支的程式碼經過程式碼評審並通過測試後,讓有許可權的管理員合併回master。

不過在實際情況中,程式碼評審不可能檢查出提交的程式碼中的所有問題,所以對於每次提交的程式碼進行自動化測試,
主分支程式碼的自動化部署尤其重要,自動化測試能在產品部署前及時發現一部分問題,如果產品部署之後發現嚴重問題,自動化部署可以在最短時間內把產品回滾到上一個版本。

優點&缺點
Github flow的優點在於流程簡單靈活,不需要考慮及管理太多的分支,適用於需要快速整合及「持續釋出」的專案,這類專案可能需要每天釋出一個版本,甚至一天釋出多個版本。但是對於應用場景比較複雜的情況,例如:多個環境下的產品部署,多個版本的釋出或問題修復,只有一個master便會顯得力不從心。

github flow這種方式,要保證高質量,對於貢獻者的素質要求很高,換句話說,如果程式碼貢獻者素質不那麼高,質量就無法得到保證。

3. Gitlab flow


GitLab flow是由GitLab 的 CEO Sytse Sijbrandij 於 2014 年正式釋出的程式碼分支管理模型,屬於GitHub flow的演進版本。

與GitHub相同之處是也存在一個長期主分支master,從master上建立新分支進行功能開發、問題修復等,結束後合併回master。
與GitHub不同之處是GitLab flow又考慮多環境部署等現實因素,增加production產品分支用於在不同的環境下部署產品,或者從master的穩定版本建立release釋出分支用於釋出軟體。

如果在產品分支或者釋出分支發現問題,就從對應版本分支建立修復分支,修復完成之後,GitLab flow遵循 「上游優先」 的合併策略,也就是將程式碼先合併到 master,再合併到下游的production或release分支。

和Github flow類似,master的修改許可權只開放給部分人,開發分支的工作完成後,程式碼通過merge request(類似於GitHub flow中的pull request)請求有許可權的管理員把程式碼合併(merge)回主分支

4. TBD flow

TBD (Trunk-based Development) flow是由Paul Hammant於2013年提出的模型。

TBD flow最大的特點是所有開發都基於主幹trunk,不再有長期的開發分支,要求所有的提交儘快回到主幹,這樣可以共用最新的程式碼,並且能儘可能地減少合併衝突。如果需要釋出版本,可以基於trunk直接生成新的分支用於釋出。

TBD flow沒有pull或者push request,要求開發人員儘快把程式碼提交到主幹分支,但是TBD flow缺乏嚴格的流程來保證每一份提交程式碼的質量,如果一些專案開發人員眾多且水平不一,同時工作在主分支上可能會在產品釋出時才發現不可預知的問題,

所以TBD flow更適用於需要快速迭代的產品,如果在主幹分支上發現問題,可以快速進行修復再合併回主幹分支。

5. TBD++ flow



TBD++ flow是Arrus公司軟體研發部門從2015年開始一直沿用的Git分支管理模型,產品專案的客戶主要是電信級服務運營商,每個國家或地區的需求在主要功能上一致,但在客戶客製化化方面又存在不少差異,同時專案開發週期較長,整個週期一般在3個月到2年之間,軟體產品在專案前期需要有快速的迭代,在專案後期需要有穩定的釋出版本。(PS: 前面這些因素是選擇該模型的重要考量因素,產品型開發,主線功能大體一致,維護客戶多,釋出週期固定且稍長)

TBD++ flow以敏捷開發為核心,同時吸收了以上幾個主流模型的優點,主要特點如下

1. 基於功能的主分支

只存在一個長期的獨立分支,即主分支master,主分支上功能齊全,通過自動測試保證基本功能執行正常,因為自動測試覆蓋不全面或者手動測試不及時,所以無法保證主分支的每個版本都是質量穩定的釋出版,但是可以根據功能的完成程度直接從主分支上建立迭代版本用於針對不同客戶或者不同時期的功能演示。基於master開發功能或者修復問題需要用到以下兩個輔助分支:

  • Feature分支:為了開發新模組或新功能以滿足客戶需求,從主分支上建立Feature分支,但是並不要求Feature分支上所有的提交儘快回到主分支,開發完成並且通過程式碼評審及功能測試後才能合併回master主分支。為了共用主分支上的最新程式碼以及避免合併程式碼時解決程式碼衝突引起的額外開銷,在功能開發過程中Feature分支需要始終與master保持同步。
  • Bugfix分支:基於主分支建立Bugfix分支修復主分支上發現的問題,修復完成並且通過程式碼評審後程式碼合併回master主分支。

基於主分支的Feature分支和Bugfix分支完成後,開發者直接將程式碼合併回主分支master,不需要像GitLab或GitHub那樣依賴於少數幾個有許可權的管理員,這是因為如果一個專案中開發人員比較多的話,管理員沒辦法做到對每部分程式碼都熟悉或掌握,所以程式碼質量交由程式碼評審和功能測試來掌控,合併程式碼回主分支的操作由開發者自己完成。

主分支上的新程式碼有時候可能因為評審或測試不全面而帶來新問題,例如破壞其他功能模組,甚至影響整體功能。為了能儘早發現問題,主分支上的每次提交都會觸發系統級自動化測試,並且週期性地對主分支進行人工測試。一旦發現問題,主分支的專職設定管理員(Software Configuration Manager,SCM)將根據問題的嚴重性和緊迫性決定是否需要直接回退引起問題的提交,或者基於master建立bugfix分支進行問題修復。

2. 基於釋出的Release分支

Release分支負責對外發布軟體產品,每個Release分支也會配備專職版本設定管理員SCM,SCM具有對Release分支的最高管理許可權。當master上已經包含了某個釋出所需要的所有功能,並且沒有已知的嚴重問題,此時由SCM從主分支上建立Release分支準備系統整合測試,和Git flow相同,在此分支上不再進行新功能的開發,僅在這個分支上進行修復問題,建立檔案,客戶引數設定及其他與釋出相關的工作,這些程式碼同時也需要合併回master以確保主分支功能的完整性。

在每個Release分支正式釋出前可能還需要將主分支上的一部分關鍵問題的修復選擇性地同步(Cherry-pick)到Release分支,這個操作也是由SCM完成。
Release分支上的工作一切就緒並通過系統整合測試後,SCM在Release分支上打上相應的版本號標籤(Tag)進行釋出,這點和Git flow在主分支上進行釋出不同。

軟體產品釋出之後,如果發現緊急或者嚴重的問題,此時需要基於版本釋出時的Release分支標籤建立Hotfix分支來修復此類問題,問題修復後合併回該Release分支以及其他同樣需要此修復的Release分支,並打上新的版本號標籤(Tag)用於釋出,同時程式碼也需要合併回master以確保主分支的健壯性。

選擇合適的分支模型

Git程式碼分支管理模型各具特點,流程只是一個輔助工具,沒有最好,只有最合適。

  • 如果開發團隊規模較小又比較分散,產品釋出週期較短(例如:初創公司,或者開發的是一個網站或 Web 應用程式,在一天內可能需要釋出多個版本),可以選擇GitHub flow或者GitLab flow;
  • 如果開發團隊規模較大,產品釋出週期較長(例如:團隊超過20人,採用了月度或季度釋出週期,並且由一個團隊負責並行開發多個專案),可以選擇Git flow,釋出週期較短可以選擇TBD flow;
  • 如果開發團隊規模大,產品釋出週期長,同時對敏捷的要求比較高,可以考慮TBD++ flow。每個組織根據產品、專案、人員的特點找到最合適的模型才是共同的目標。對於某個長期產品的開發和客戶版本維護場景,這種分支是筆者比較推薦的。

以上這些分支策略,僅僅是作為大家實踐的參考,不同的開發模式和釋出節奏,以及團隊的人員水平,基礎設施水平等都是選擇分支模型的參考因素。

參考