歡迎光臨
每天分享高質量文章

Git Flow分支策略與Azure DevOps相關功能簡介

想了很久,還是寫這麼一篇文章來總結一下有關分支策略和DevOps的一些內容吧。其實,DevOps相關的內容並不是我的工作範圍,不過對於敏捷開發、DevOps、專案管理等等這一系列的與開發過程相關的內容,我還是有些經驗的,也就抽時間跟大家分享一下吧。

Git Flow應該是很多基於Git分佈式版本控制系統的專案所實踐的一種開發流程,當然,很多人對於Github非常熟悉,甚至平時工作就是基於Github的。在此我也就不多介紹Git以及Github的概念了,只需要知道Github是基於Git的一個服務供應商,目前已被微軟收購。Git Flow就是由Vincent Driessen基於Git這一版本控制系統所總結出來的一套可行的、能夠滿足很多專案開發需求(註意:不是大多數專案)的敏捷開發流程,英語水平好的朋友可以參考閱讀Vincent的原文:《A successful Git branching model》。

Git Flow通常會用在有具體的release發佈的概念的專案上,簡言之就是類似於以前能夠給客戶提供安裝包的專案,對於SaaS專案,Git Flow還是太重了,而且不同環境、多租戶的部署策略也與Git Flow有一些差別。因此,團隊還是應該根據自己的實際情況來選擇合理的開發流程,這裡所介紹的內容也是僅供參考。下圖(來自《A successful Git branching model》一文)展示了Git Flow的整個流程,在這裡,我會對這個流程做一個詳細的介紹。

master分支

master分支始終保持了最近一次發佈(release)的代碼,通常情況下,通過tag的方式來標記每一次release。在Github中,每創建一次release,就可以基於某個分支(branch)創建一個tag。在tag被創建後,分支是可以刪除的。因此,我覺得在上面的模型中,維護一個master分支並不是必需的。所以,有些團隊為了直觀,會將develop分支作為預設分支,甚至刪除master分支。但我覺得刪不刪除也都無所謂,直接將master分支作為開發分支(也就是合併develop和master的職責)也是可以的。

develop分支與feature分支

develop分支(或者master分支),是專案開發的主要分支,它包含了專案的最新代碼,開發和測試團隊都會基於develop分支進行工作。每當有新的功能需要開發時,都會從develop分支分出一個feature分支。從實踐的角度:

  • 上圖中分主體功能的feature分支(Major feature for next release)以及後續版本的feature分支(Feature for future release),實際上,出現後續版本的feature分支的可能性不會太大,由於採用敏捷開發,團隊通常不會做三個月以上的專案計劃,因為沒有意義,沒有人能夠確保三個月之內不會有功能需求的變更、backlog的調整以及市場對於專案本身的影響,因此,相對而言,近期的版本發佈標的應該是比較明確的,長遠的計劃反倒顯得意義不大。不過,也有可能會讓團隊的部分成員提前進入下一版本的研發,但由於敏捷開發和微服務理念的引入,一般敏捷團隊也不會特別龐大,所以,這樣的活動也不太會頻繁發生。當然,還是應該依據專案實際情況而定,如果真有部分成員提前進入下一版本開發的需要,那就按上圖中所描述的流程進行即可,不會有什麼大問題
  • 多個feature並存的可能性還是很大的,團隊的不同成員會工作在不同的feature分支上,當每個feature完成之後,都會合併到develop分支。合併過程可能會出現代碼衝突
  • 每個成員是直接將代碼提交到feature分支,還是自己再基於feature分支創建自己的工作分支?這取決於團隊的代碼審核(Code Review)流程,如果團隊有嚴格的代碼審核流程,開發人員應該在進行開發工作之前,基於feature分支創建自己的工作分支。開發完成後,將代碼push到遠程,然後提交Pull Request(PR)並邀請團隊進行Code Review,Review通過,再將代碼合併到feature分支,代碼合併之後,將自己的工作分支刪掉即可。如果代碼審核流程不嚴格,那麼直接將代碼push到feature分支也是可以的,這需要團隊成員建立起互信機制,並且有高度自治(Self-organize)的能力。這裡有兩點可以多寫幾句,首先不要覺得重覆創建、刪除分支會帶來很大壓力,Git的分支是非常輕量的,需要的時候就創建,不需要就刪除,非常方便;其次,很多持續集成系統,對於多分支的開發流程以及Pull Request/Code Review流程都有完美的支持,Azure DevOps的這部分功能使用起來也是非常方便,之後我會詳細介紹
  • 持續集成系統會從各feature分支上拉取代碼進行編譯,然後自動化部署到開發環境進行冒煙測試(Smoke Test),便於開發人員儘早驗證已開發的功能。如果驗證通過,開發團隊可以將feature分支合併到develop分支,並刪除feature分支,然後進行下一個feature的開發
  • 持續集成系統會從develop分支上拉取代碼進行編譯,然後自動化部署到測試環境供測試團隊(QA)進行測試,最後給Product Owner或者其他Stakeholders做演示的環境,也是從develop分支出來的

release分支

當所有計劃好的feature都完成之後,團隊會基於develop分支創建release分支,此時:

  • 持續集成系統會基於release分支產生新的構建,構建結果稱為Beta構建(Beta Builds)
  • 測試團隊(QA)基於Beta構建進行回歸測試(Regression Testing)
  • release分支不接受任何新的功能增加
  • 開發團隊在release分支上進行Bug修複,同樣,修複Bug時是否需要創建自己的代碼分支,取決於團隊自己的決定
  • 當質量達標,團隊驗收之後,進入release流程,此時,基於release分支創建release tag,同時將release分支合併回develop分支,以將release分支中的bug修複帶入develop分支。在建完release tag並將代碼合併回develop分支後,可將release分支刪除。上圖中沒有體現這一步
  • 上圖中展示的是將release分支合併到master分支,然後在master分支上建release tag,這樣做是不妥的,因為合併到master分支的代碼並沒有經過測試,所以release tag不能建立在master分支上

hotfix分支

在某個版本發佈之後,有可能會得到用戶的反饋,有些是功能性的,有些則是影響用戶使用的問題。對於功能性的反饋,可以與用戶商量,或者團隊自己決定,是準備在下一個版本中加入,還是基於用戶現在的版本為用戶專門定製。如果是後續版本再支持,則遵照上述feature分支的策略即可,但如果是基於用戶現在使用的版本進行定製,則需要走Hotfix的流程

  • Hotfix分支從已經release的tag創建,找到已有的tag,然後基於tag新建Hotfix分支即可
  • Hotfix分支的工作流程可以參考develop分支
  • Hotfix開發完成並檢驗通過之後,基於Hotfix分支創建tag,標記為某一個Hotfix
  • 根據當前所修複的問題是針對該特定用戶的(比如在界面上增加用戶公司的名稱與logo),還是針對所有用戶的(比如某個bug的修複),以此決定是否需要將改動合併到develop分支
  • 刪除Hotfix分支

從上面的流程可以看出,除了develop分支(或者master分支)為長期存在的分支之外,其它的分支都為輔助分支,在工作完成之後可以立即刪除。為了滿足代碼評審(Code Review)而創建的開發人員自己的分支,一般都是即用即刪。

以上就是Git Flow的整個流程,應該是已經介紹的比較細緻了。在平時的工作和自學中,我都是以Github作為代碼托管平臺的,因此,本文的內容仍然是以Github為基礎,包括接下來有關Azure DevOps Pipeline的介紹,也是與Github進行集成的。

在上面的介紹中,不止一次提到持續集成系統,比如,當有代碼簽入feature分支或者develop分支時,持續集成(Continuous Integration,CI)系統會自動進行編譯,然後觸發持續發佈(Continuous Delivery,CD)系統完成自動化部署。這些CI/CD系統所執行的自動化任務,需要人為地反覆定義並觸發嗎?其實並不需要。現在流行的持續集成系統基本都已成熟,比如Jenkins,它的Pipeline功能直接支持Multi-Branch,每當有新的分支創建,或者代碼簽入,都會觸發Jenkins創建新的Job,並觸發相應的CI任務。Azure DevOps在這部分也做得非常好,而且它是雲端服務,簡單易用,對於開源專案是完全免費的。

首先,當你在Github中新建了一個repo,並且在Azure DevOps中配置了一個Project,使其從Github拉取代碼時,你會發現,Github repo的Webhook里已經自動為你加上Azure DevOps所需的Webhooks:

不用管它,我們設想兩個場景:

  1. 當開發人員準備向feature分支合併代碼時
  2. 當feature分支出現代碼簽入時

下麵看看,如何在Azure DevOps中進行配置,以實現上述兩個場景。在這個實驗中,我的Github Repo有三個分支:

  • master:暫時沒用到
  • dev:開發主線,保持了最新代碼
  • features/a1:功能代號為a1的開發分支

目前團隊都在集中開發features/a1功能,由於團隊選擇較為嚴格的Code Review流程,因此,開發人員在進行自己工作之前,都是從features/a1創建自己的工作分支,比如就叫features/a1-daxnet吧,以便在代碼簽入features/a1分支的時候,能夠產生Pull Request並申請代碼審查。工作分支的名稱可以自己決定,但團隊需要達成共識,因為這個名稱之後會被Azure DevOps用到。

現在,進入Github Repo的Settings頁,在Branches設置頁面中,在Branch protection rules設置下,新建一個規則(Rule),在Branch name pattern中,輸入features/a1(也可以使用規則來定義一組分支),然後,勾選Require status check to pass before merging:

註:如需Code Review,則還需要勾選Require pull request reviews before merging,在這裡就不演示了。然後,回到Azure DevOps,針對Github Repo創建CI,在CI的Trigger選項中,啟用Continuous integration,以保證每當有代碼簽入指定的分支,就會觸發持續集成。在Branch filters中,添加features/*分支,表示以features作為開頭字符的所有分支,都需要進行持續集成,確保編譯通過:

啟用Pull request validation,在Branch filters中,添加features/a1,表示當有Pull Request需要合併到features/a1分支時,也需要進行持續集成,以確保編譯通過。註意,目前我們不涉及Repo被Fork的情況,所以我們不勾選Forks選項:

OK,基本設置就是這樣,非常簡單。接下來,我們開始開發新的功能。首先,在Github頁面基於features/a1,創建分支:features/a1-daxnet:

剛剛創建完新的分支,Azure DevOps就已經開始工作了,可以看到,Build Pipeline已經完成了新分支的編譯:

下麵,我要開始修改代碼了,在代碼修改完成本地編譯通過之後,我將代碼提交到features/a1-daxnet分支:

再次查看Azure DevOps的Build Pipeline,可以看到,CI已經開始幫我們編譯新的代碼提交了:

OK,再次不管它,現在,我希望將代碼合併到features/a1分支,於是,我到Github上創建Pull Request,此時Github會提示,代碼校驗還在進行中,並等待Azure DevOps的編譯結果:

回到Azure DevOps,可以看到,Build Pipeline正在進行Pull Request編譯:

等待編譯成功後,開發者就可以將代碼合併到features/a1分支了。當然,這裡我沒有強制要求必須要等代碼編譯成功才能合併分支,因此,即使是編譯沒有完成,上圖中的Merge pull request的按鈕也是可用的。

本文首先介紹了Git Flow分支策略,並結合了實際應用介紹了Git Flow的詳細步驟,然後基於Azure DevOps介紹了在實際應用中,Azure DevOps Build Pipeline對Git Flow的支持。本文所介紹的內容並不能完全適用於所有的軟體專案,尤其是SaaS專案,所以在開發過程中,團隊還是應該根據自己的實際需求來定製自己的開發流程,在保證軟體質量的前提下,提高開發體驗和團隊生產力,探索尋求適合自己的實踐流程。

原文地址:http://sunnycoding.cn/2019/03/23/git-flow-and-azure-devops/

赞(0)

分享創造快樂