CI/CD Server Note 03

GitLab Flow

git是現在大部分開發團隊所使用的版本控制軟體,但git本身只是工具而已,對於開發流程來說需要一個工作流來使其可靠且有效率的運作。

工作流

工作流 (Workflow),如同字面上的意思即工作流程,在專案開發中,因為多人協作會產生許多分支,雖然在各自的分支上互相不干擾,但是多人協作開發專案總會需要把分支合併在一起,而在實際專案中這會涉及許多問題,比如說版本疊代、版本發佈、Bug修復等等,而要將所有人的代碼管理、整合起來,需要制定一套工作流程,這個就是所謂的工作流。

工作流不涉及工具、命令,他只是一種規則,而這個規則完全由開發者或是專案管理者來定義,目前使用度最高的工作流分別是以下三種

其中Git Flow出現的最早,接著Github Flow因為持續的版本發布需求在Git Flow的基礎上做了一些優化,而GitLab Flow出現的時間最晚,它是綜合前面兩種工作流的優點進而制訂的一個工作流。

Git Flow

Vincent Driessen在2010發布他自己的分支管理模型: Git Flow,目前使用度仍然非常的高,我最先接觸的工作流就是Git Flow,他綜合考慮了開發流程中會遇到的所有情況,不過也就是因為考量到了所有情況,實際應用起來非常的複雜。

Git Flow的分支結構按功能來說,可以分為五種不同的分支,從這五種分支的生命週期上來說,又可以分成長期分支和短期分支,或者按照功能性來說分為主要分支和協助分支,下面這張圖說明了整個Git Flow的開發流程:

這張圖中畫了Git Flow的五種分支:master、develop、feature、release和hotfix,可以透過圖中的箭頭清楚的看到分支開始和結束的走向,其中master和develop字體被加粗代表主要分支,master每合併一個分支,無論是hotfix還是release都會打上一個版本標籤。

主要分支

當開發的專案使用Git Flow工作流,程式碼的儲存庫會一直存在以下兩個長期分支:

  • master
  • develop

其中master分支上的程式碼永遠是最新發佈的版本,是主要呈現給客戶的產品版本,這個分支的來源只能從別的分支合併過來,因為是穩定版通常在這分支上會有版本編號。

develop是所有開發的基礎分支,當要新增功能時,會新增協助分支feature分支,開發完後再合併回develop,當認為develop分支上的程式碼夠成熟時,會合併到release分支,在這邊進行上線前的最後測試,完成後,會同時合併到master和develop這兩個分支上,合併回 Develop 分支的目的是因為可能在release分支上還會測到並修正一些問題,所以需要跟 develop同步,免得之後的版本又再度出現同樣的問題。

協助分支

除了主要分支,Git Flow還需要一系列的協助分支來幫助更好的併行開發、簡化功能開發和bug修復,這類分支在需要的時候創建,用完後可以直接刪除,是具有生命週期的分支,也就是以下三類分支:

  • feature
  • release
  • hotfix

當需要開發新功能時會使用feature分支,命名隨開發者喜好,只要不要跟其他分支有衝突就好;feature分支都是從develop開過來的,完成後會再合併回develop分支,然後刪除自己,這裡要注意的是多個feature分支合併時容易遇到衝突,所以feature的功能最好切越小越好,並且要縮短開發的時程來降低發生衝突的機率。

release就像上面develop分支所敘述的是用來作為發佈版本的預發佈分支,建議命名為release-x.xx.xx,例如當在release-1.0.0測出小問題,會在release分支進行修改提交,測試完畢準備發佈時會合併到master和develop,在master會打上對應的版本標籤v1.0.0然後刪除自己,這樣做的好處是在測試時,不會影響到下一個版本的開發。

hotfix分支是用來修復線上緊急bug的分支,當上線的某個版本出現了問題,將會找出對應版本的程式碼,創建hotfix分支,問題修復後,會合併回master和develop,然後刪除自己,要注意的是合併到mater時要打上修復後的版本標籤,說明已修復該bug,另外會合併到develop是因為不合併的話,develop就會有相同的bug出現。

GitHub Flow

GitHub Flow看名稱可以知道是由GitHub制定並使用的工作流,由scott chacon在2011年正式發佈,主要的目的是簡化Git Flow的流程,因為對於大部分開發者和團隊來說,Git Flow稍嫌有點複雜,GitHub Flow適合在部署上自動化且需要一天多次部署的工作流 (持續部署),為了更好的解決這些問題推出了GitHub Flow。

比起Git Flow來說,GitHub Flow可以說是相當簡單明瞭了,GitHub Flow推薦作法是只有一個主要分支master,其他人開發者要操作得透過分支通過Pull Request來合併到master上,下面是GitHub Flow的流程圖:

GitHub Flow流程說明

GitHub Flow聽名稱就是要跟GitHub一起配合的工作流,整個流程如下:

  1. GitHub Flow可以看到只有一個分支master,而且這個分支上的程式碼永遠是處於可發布狀態;根據需求開發者從master拉出新分支 (branch或是fork),這個分布不需要區分是甚麼類型的分支。
  2. 當新分支開發完或是需要討論時,就向master發起Pull Request (簡稱PR)。
  3. 這個Pull Request可以看作是一個通知,讓該儲存庫的所有團隊注意到你的請求,可以算是一種對話機制,所有關注這個儲存庫一起評審、討論提交的代碼,當然在討論過程中,還可以不斷提交程式碼。
  4. 提交的Pull Request經過討論和修改後,會嘗試部署、測試,當確定沒有問題時,會合併 (merge) 進master,原先提出的保存了當時的修改紀錄和回饋,可以讓後續的開發人員回頭檢視當時的情況。

GitHub Flow因為Pull Request會讓程式碼在線上跟各個開發者討論,如果程式寫的很爛,就等著被其他人review的吐槽吧~🤣

GitHub Flow特色

  1. Pull Request:
    GitHub Flow的特色之一,它的用處不僅僅只是合併分支,還可以很好的控制分支的合併權限,不是想合併就合併;可以透過Pull Request來討論問題,或是請求其他開發者的協助。
  2. Issue Tracking:
    在開發中,如果遇到問題可以給專案標記issue,用issue的開啟和關閉來得知該問題是否解決或是了解其解決的思路;除此之外,還可以對issue打上不同的標籤,來追蹤不同類型的issue;如果當前提交的程式碼是解決某一個issue時,可以在Commit Message中帶上fix #X的訊息,可以自動對應到該編號對應的issue。

GitLab Flow

GitLab Flow結合了Git Flow和GitHub Flow兩者、汲取了兩者的優點,它最主要的原則叫做上游優先 (Upsteam First),整個儲存庫只存在一個主要分支master,它是其他所有分支的上游,所以分支合併的順序很重要,要確保上游分支提交的程式碼通過測試才可以往下游合併、應用到其他的分支,除非是緊急情況,才允許跳過上游直接在下游操作合併。

GitLab Flow分成兩種情況來應付不同的開發流程:

  • 持續部署
  • 版本發佈
💡
不論使用以上哪種狀況,都必須要遵守GitLab Flow最大的原則上游優先 (Upsteam First)

持續部屬

對於持續部署 (CD),GitLab Flow建議在master分支外,再去建立不同的環境分支,比如說,開發環境的分支是master,預發環境的分支是pre-production,生產環境的分支是production,如果還有其他測試環境還可以新增其他分支,不過需要遵守前面所說的上游優先規則,如下圖:

由上圖來舉例,如果生產環境 發生了bug,則要建立一個新分支,修復bug後得合併到最上游的開發環境 ,接著經過測試再繼續往預發環境合併,同樣也得通過測試後才能往下合併到生產環境

版本發佈

當需要對外發佈產品時,會需要創建release分支,其中對外發佈版本的紀錄是十分重要的,如果上線後出了一個bug,需要找到問題出現所對應版本的程式碼,才能準確的定位問題。

在GitLab Flow,建議是每一個穩定版本都要從master拉出一個分支,比如下圖的2-3-stable、2-4-stable,等到發現問題時,就從對應版本分支分出修復分支,當完成之後,要記得先合併到master才能利用cherry-picks來將修復的程式碼應用到release分支 (記得要更新版本號),要遵循上游優先原則。

總結

Git Flow的優點很明顯,所有的情況都有對應的分支可以去處理,但也因為考慮到了所有情況,導致應用起來相對複雜了許多,需要頻繁地切換分支;如今軟體的開發大部分都是快速迭代的情況下,是幾乎用不到hotfix和release分支的,因為合併到master後如果有bug就直接修復然後再發佈下一個版本就行了,如果還使用這兩個分支,那修復完成後,還需要合併回去develop和master分支,但實際上開發者很容易忘記合併回去。

GitHub Flow則是適合持續部署類型的開發,缺點是主要分支master上最新的提交為最新版本,但是準備要發佈的版本不一定是用這個最新的版本,如果只有一個master主分支就會不夠用,所以還得另外再建一個新分支來維護,所以後來又發展出了GitLab Flow。

這三種工作流有 一個共同點,都是功能區動式開發 (Feature-driven Development),以需求為開發的起點,先有需求才會有分支,且開發完分支後就會被合併到主分支然後刪除該分支。