在本文中,我們將依據 A successful Git branching model一文,解說並示範幾種開發情境可以應用的分支策略模型,不論是大型專案或小型應用程式,皆可套用於其中,並享受分支策略模型所帶來的效益。
在文章裡有關專案(project)的任何細節將不被談論,只談論分支(branching)的策略及發佈(release)的管理。
下圖即是整個分支策略的概觀:
後續小節將敘述相關分支策略的細節。
主要分支(main branches)
上圖中最主要的分支有 2 個,主分支(master/main)與開發分支(develop),實務上也可能把 develop 簡化為 dev 。
這 2 個分支各司其職,以下將分別介紹 2 大分支:
- 主分支(master/main):處於 production-ready 的狀態,換句話說,即是該版的 source code 是可運行的、符合專案需求的、設計良好的、穩定的、可維護的、可擴展的及已文件化的。
- 開發分支(develop):下次發佈版本的最新狀態。從主要分支分出來。有些開發者也稱開發分支為整合分支,自動化測試所根據的程式碼(source code)即是以此分支上的版本為基準來進行測試。
當開發分支上的 source code 達到一定穩定程度,並準備發佈時,即可將該分支上的變更合併回主要分支,並標上發佈的版本號。這就是所謂的新產品發佈。
支援分支(Supporting branches)
除了主分支,我們也會使用支援分支來幫助專案開發。支援分支可讓整個團隊更容易管理新功能的開發、產品發佈分支或是快速修正一些 bug。
支援分支與主要分支最大的差別在於,支援分支在支援任務結束後就會移除,而主要分支則是始終存在。
本文中我們所使用到的支援分支有:
- 功能分支(feature)
- 發佈分支(release)
- 修補分支(hotfix)
每一個支援分支都有其特殊支援目的,並嚴格遵循分支與合併的規定。例如:功能分支(feature)只能從開發分支(develop)分離出來,也只能與開發分支(develop)合併。
功能分支 (feature branch)
功能分支顧名思義就是開發新功能的分支。
功能分支原則:
- 從開發(develop)分支分離。
- 必須合併回開發分支。
- 分支命名規則:除了
master/main
,develop
,release-*
, 或hotfix-*
以外的功能名稱都行。
只要新功能未開發完成,功能分支就會持續存在直到開發完成並合併回開發分支或直到放棄開發此新功能。
開功能分支詳細步驟:
- 開「功能」分支 ,從開發分支分出名為 feature/blah 的分支,開完後切換到 feature/blah 分支:
$ git checkout -b feature/blah develop
- 將已開發完成之功能分支合併回 develop 分支:
$ git checkout develop # 切換至開發分支
$ git merge --no-ff feature/blah # 將feature/blah分支合併到開發分支
$ git branch -d feature/blah # 刪除feature/blah分支
$ git push origin develop # 將開發分支 push 到遠端 origin
--no-ff
參數會將被合併的分支的 commits 打包成 1 個 commit,避免合併後的分支上出現多個 commits ,整合成單一 commit 的好處在於容易追查問題,可以迅速追到是哪個 feature 有問題(因為每個 feature 被合併後只有 1 個 commit),也可以輕易的 revert 某個功能。
有沒有加 --no-ff
的差異如下圖所示:
右圖中是沒有加入 --no-ff
的情況,所以無法看見哪些提交(commit)是專門因為開發新功能而產生的,若有追蹤程式碼的需求時,開發者必須得要自行閱讀所有的log訊息才能知道問題也許出在哪一個版本,相較之下較為不便。
發佈分支 (release branch)
發佈分支是為了發佈新版本而存在的,換言之,可以說是將程式碼與主分支(master/main)合併前的過渡階段,是發佈新版本之前所必須進行的相關手續。在此分支必須進行一些整合性測試,並進行小 bug 修復及增加一些metadata(例如版本號或是 build 日期等)。
有了發佈分支,開發分支就可以只需專注接收功能分支(feature)所合併進來的功能即可。
一般而言,當產品開發到一個階段時,發佈產品的需求就會自然顯現。此時,即是發佈分支的關鍵時刻。在此階段,這次發佈的所有新功能就需要合併(merge)到開發分支(develop),接著再由開發分支(develop)分出發佈分支,開始進行相關發佈前的手續。
制定版本號碼的最佳時機是在發佈(release)分支上。進到發佈分支之前,開發分支上會有許多「為了下一次發佈」所合併的新功能,但對於版本號是多少,尚無法確認,而發佈分支便是為了確認版本號等其他事情而存在的。
版本號的制定規則從專案一開始時就需制定,而且必須嚴格遵循版本號的制定規則。如果有需要的話,可以進一步參考 Semantic versioning 。
發佈分支原則:
- 從開發分支分離。
- 合併回開發分支或主要分支。
- 分支命名規則:
release-*
發佈分支詳細步驟:
- 從開發分支開一支名為「release-1.2」的分支,並切換到 release-1.2 及制定版本號, commit 一個版本,commit 訊息為「 版本號 1.2 」:
$ git checkout -b release-1.2 develop
$ git commit -a -m "Bumped version number to 1.2"
- 將已制定好 metadata 或已修復小 bug 的發佈(release)分支合併到主要分支 :
$ git checkout master # 切換至主要分支
$ git merge --no-ff release-1.2 # 將 release-1.2 分支合併到主要分支
$ git tag -a 1.2 # 上 tag
- 將已制定好 metadata 或已修復小 bug 的發佈(release)分支合併回開發分支 :
$ git checkout develop # 切換至開發分支
$ git merge --no-ff release-1.2 # 將 release-1.2 分支合併回開發分支
- 刪除 release-1.2 分支 :
$ git branch -d release-1.2
上述流程在實務上也可以簡化為將 master/main 主線視為 release 分支,直接將 develop 併入 master/main 後,上 tag 之後就發佈
修補分支 (hotfix branch)
修補分支的誕生,通常是因為出現了一個急需在短時間內修復的 bug,無法等到下一次發佈時才修復,例如與伺服器間的通訊有 bug,需要馬上進行更新修正或是資安問題極需馬上修正。
此分支通常從主分支某個已標上 tag 的 commit 分出, bug 經過修復後,可合併到開發分支,或者是合併回主分支,並標上新的版本號 tag。
開此分支的好處在於開發分支上的成員可以繼續原本的工作,而 bug 修復工作也同時可由另外的成員執行,將對彼此間的影響降到最低。
修補分支原則:
- 從主分支分離。
- 合併回開發分支或主分支。
- 分支命名規則:
hotfix-*
開修補分支詳細步驟:
- 開修補分支 (hotfix branch),從主線分支(master/main)開一支名為「hotfix-1.2.1」的分支,並切換到 hotfix-1.2.1 分支:
$ git checkout -b hotfix-1.2.1 master
或者也可以選擇從特定 tag 分出修補分支,例如修正版本 1.2 的 hotfix 可以指定從 1.2 開分支:
$ git checkout -b hotfix-1.2.1 tags/1.2
- 制定版本號, commit 一個版本,commit 訊息為「版本號 1.2.1」
$ git commit -a -m "Bumped version number to 1.2.1"
- 修正 bug 並 commit 一版 :
$ git commit -m "Fixed severe production problem"
- 將修正完 bug 的修補分支合併回主分支 :
$ git checkout master # 切換至主要分支
$ git merge --no-ff hotfix-1.2.1 # 將 hotfix-1.2.1 分支合併到主要分支
$ git tag -a 1.2.1 # 上 tag
- 將修復完成的修補分支合併回開發分支 :
$ git checkout develop # 切換至開發分支
$ git merge --no-ff hotfix-1.2.1 # 將 hotfix-1.2.1 分支合併回開發分支
需要特別注意的是,若修補分支與發佈分支同時存在,則當 bug 修補已完成時,就不是合併回開發分支,而是發佈分支。如此一來,修補程式就會在未來跟著發佈分支合併回開發分支時。
- 刪除 hotfix-1.2.1 分支 :
$ git branch -d hotfix-1.2.1
總結
以上就是 Git 分支模型的詳細說明。
當然,本文所解說的也只是一種分支策略的框架,不一定要百分之百依循,可以隨自己的喜好化用不同的策略模型,因此業界也演化出各式分支模型,不過基本上都大同小異,本文學到的技巧也都可應用到其中。
Happy Coding!
References
A successful Git branching model