貓頭鷹的深夜翻譯:開發者必須瞭解的分支發佈模型

前沿

本文只會聚焦於分支發佈策略,不會涉及任何的項目細節。
分支發佈模型圖git

爲何選擇Git

想要深刻了解Git和中心化代碼版本管理系統的優缺點比較,能夠在網上自行查詢,這個話題一直爭論不休。做爲一個開發者,我更傾向於使用Git。Git確實改變了開發者對代碼合併和分支管理的認識。做爲一個使用過傳統的CVS工具的人,合併/開分支是一個比較恐怖的行爲,無可奈何才執行一次。shell

可是,Git的分支合併和建立操做就很是簡單,這些操做已經被是爲每日工做流的一部分。好比,在介紹CVS的書本中,分支和合並只會在末尾的章節面向高端開發者介紹一下,而在每一本說Git的書中,基本上在第三章就會說明。安全

由於Git在這個操做上的簡潔性和重複性特性,分支開發和合並再也不是一件可怕的事情。版本控制工具本就應當更好的幫助分支的建立和合並。服務器

不談工具,接着要介紹開發模型。今天我要介紹的這個模型本質上是一組流程,每一個團隊成員經過遵循這一組流程來管理軟件開發過程。併發

去中心化又中心化

在分支發佈模型中,咱們會設置一箇中心化的「真理」倉庫。這個倉庫只是名義上的中心倉庫(由於Git是一個去中心化的倉庫,所以從技術角度上來講這個倉庫不是中心化的)。咱們將該倉庫標記爲origin,由於origin這個命名對於全部的Git用戶來講都是很熟悉的。
工具

每一個開發者從origin拉取和上傳代碼。每一個開發者之間也能夠從彼此的代碼倉庫拉取或構件子代碼團隊。這種方式適用於大型團隊,即子團隊能夠先在一個團隊分支上進行特性開發,在特性穩定後再提交到origin倉庫。spa

主分支

中央倉庫持有兩個擁有永久生命週期的分支:master和develop
origin倉庫中的master主分支對每一個Git用戶都是再熟悉不過的了。和master分支平齊的分支稱爲develop開發分支。
版本控制

origin/master分支是項目的主分支,源代碼的HEAD標籤永遠指向了該分支上的一個可發佈版本。日誌

咱們將origin/develop分支是爲另外一種類型的主分支,該分支上的代碼始終處於一個穩定的可發佈的狀態。該分支上的全部變動都應當被合併到master分支上,並搭上一個發佈標籤。具體的操做將在後文詳細描述。code

所以,每當變動被合併到master分支上時,都意味着釋放了一個新的發佈版本。咱們嚴格的遵循這必定義,所以理論上來講,每當有一個代碼提交至master分支上,咱們應當使用Git鉤子來自動構建和發佈代碼到生產環境服務器。

輔助分支

在主分支master和develop以外,開發過程模型還使用了各類輔助分支來實現團隊成員間的並行開發,簡化功能開發,作生產發佈的準備工做和快速修復生產環境的故障。和主分支不一樣,這些分支都有着必定的生命週期,由於他們最終都會被刪除。

輔助分支的類型包括:

  • 特性分支 Feature Branch
  • 發佈分支 Release Branch
  • 修復分支 Hotfix Branch

每一類分支都有着特定的目標,而且受限於不一樣的約束,好比該類分支應當從哪類分支中生成,最終合併到哪類分支中去。

可是這些分支從Git的角度上來講並沒有區別,它們就是一般意義的Git Branch,只是咱們賦予了他們不一樣的使用語義。

特性分支 Feature Branch

來源分支:develop開發分支
合併分支:develop開發分支
分支命名規範:master, develop, release-, 和 hotfix-


特性分支是爲了支持將來上線的新功能來進行開發分支。在開始特性分支開發時,對應的將來的發佈分支多是未知的。特性分支的精髓在於只要該特性還在開發中,該分支就會一直存在,並會最終合併回develop開發分支(肯定該特性會被髮布)或是被拋棄(特性的開發結果沒有達到預期)。

特性分支通常只存在於開發者的倉庫中。

建立特性分支

$ git checkout -b myfeature develop
Switched to a new branch "myfeature"

合併開發完成的特性分支到develop分支中

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff myfeature
Updating ea1b82a..05e9557
(Summary of changes)
$ git branch -d myfeature
Deleted branch myfeature (was 05e9557).
$ git push origin develop

--no-ff標籤使得合併操做建立一個新的提交記錄,即便該合併能夠被fast-forward快速合併到目標分支中。這種方式避免了全部在feature分支上的歷史提交記錄的丟失。對好比下:

右圖中沒法從Git提交歷史中看出來哪些提交記錄構成了feature分支,你須要手動閱讀全部的日誌消息。回滾特性代碼在右圖中是一件很是麻煩的事情,可是經過--no-ff合併的左圖中就比較容易。雖然它會建立更多的提交記錄,可是總的來講優勢大於缺點。

發佈分支 Release Feature

來源分支:develop開發分支
合併分支:develop開發分支和master主分支
分支命名規範:release-*

發佈分支支持爲一個新的生產環境發佈作準備。它容許在上線以前進行最後的操做。除此之外,它容許小的bug修復和發佈前的元數據準備操做(版本號,構建日期等)。經過在發佈分支上作這些事情,開發分支變得更加簡潔,只須要接收將來會發布的新特性。

當開發分支基本達到了發佈一個新版本的狀態時,須要從開發分支建立一個新的發佈分支。全部知足發佈條件的特性分支此時必須已經被合併到開發分支中。而還沒有達到發佈條件的特性分支無需合併到master分支,它們必須等到發佈分支生命週期結束後才能合併到開發分支上。

在建立發佈分支時,會爲本次發佈定義一個版本號(不會早於此)。直到這一刻,用於下一次發佈的開發分支才知道本身下一次的發佈版本號爲0.3仍是1.0。在發佈分支建立時會按照版本號的演進規則決定本次發佈的版本號。

建立發佈分支

發佈分支建立於開發分支。好比,假設當前生產環境的版本號爲1.1.5,而且接着會有一個重大的發佈。此時開發分支已經達到了下一次發佈的要求,而且咱們決定該版本爲1.2(不是1.1.6或是2.0)。因粗咱們建立分支而且在發佈分支的命名中帶上了新的版本號:

$ git checkout -b release-1.2 develop
Switched to a new branch "release-1.2"
$ ./bump-version.sh 1.2
Files modified successfully, version bumped to 1.2.
$ git commit -a -m "Bumped version number to 1.2"
[release-1.2 74d9424] Bumped version number to 1.2
1 files changed, 1 insertions(+), 1 deletions(-)

在建立了新的分支並切換到該分支上後,咱們開始切換版本號。在此處,bump-version.sh是一個虛擬的shell腳本,它會在發佈版本文件上執行一些版本操做(固然了這些操做能夠經過手動完成)。接着,版本操做被提交。

這個新分支會存在一段時間,直到發佈被徹底執行。在此期間,能夠在分支上修復bug(而非develop分支上),可是禁止添加大的新特性。它們必須先被合併到開發分支,而後等待下一個發佈節點。

結束髮布分支

當發佈分支確實能夠發佈時,在此以前須要執行一些操做。首先,發佈分支被合併到master分支上。接着,提交到master分支上的代碼必須打上標籤,從而在將來能夠引用該歷史版本。最後,發佈分支上的代碼必須被合併會開發分支,使得開發分支上的代碼也包含了發佈版本的內容以及修復的bug。

$ git checkout master
Switched to branch 'master'
$ git merge --no-ff release-1.2
Merge made by recursive.
(Summary of changes)
$ git tag -a 1.2

此時發佈已經完成,而且打上了標籤以便引用。
接着將變動合併會develop分支:

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff release-1.2
Merge made by recursive.
(Summary of changes)

這一步合併操做可能會存在衝突,須要解決衝突並提交。
在這些都完成後,咱們能夠刪除掉髮布分支,由於咱們再也不須要該分支了:

$ git branch -d release-1.2
Deleted branch release-1.2 (was ff452fe).

修復分支 Hotfix Branch

來源分支:master主分支
合併分支:develop開發分支和master主分支
分支命名規範:hotfix-*

修復分支和發佈分支很接近,由於它們都是爲了生產環境發佈作準備的一個分支。修復分支產生的原因在於須要馬上對生產環境中的代碼進行快速變動。當生產環境版本代碼出現重大bug須要馬上處理時,能夠從對應版本的生產環境代碼拉一個修復分支進行處理。

該分支的核心點在於團隊的其餘成員能夠繼續基於開發分支進行開發,而負責修復的成員能夠獨立的快速修復生產環境問題。

建立修復分支

修復分支建立於master分支。好比版本1.2是當前正在運行的生產環境版本,而且由於一個缺陷出現了故障。可是開發分支上的代碼尚不穩定。咱們須要建立修復分支並開始修復問題:

$ git checkout -b hotfix-1.2.1 master
Switched to a new branch "hotfix-1.2.1"
$ ./bump-version.sh 1.2.1
Files modified successfully, version bumped to 1.2.1.
$ git commit -a -m "Bumped version number to 1.2.1"
[hotfix-1.2.1 41e61bb] Bumped version number to 1.2.1
1 files changed, 1 insertions(+), 1 deletions(-)

切換新的發佈版本後不要忘了切換代碼中的版本號
接着在一次或屢次提交的代碼中修復問題。

$ git commit -m "Fixed severe production problem"
[hotfix-1.2.1 abbe5d6] Fixed severe production problem
5 files changed, 32 insertions(+), 17 deletions(-)

關閉修復分支

修復完畢後,修復分支須要合併會主分支,也須要合併回開發分支,從而確保該修復包含在下次發佈代碼中。這與發佈分支的關閉過程徹底相同。
首先,更新master代碼的標籤併發布:

$ git checkout master
Switched to branch 'master'
$ git merge --no-ff hotfix-1.2.1
Merge made by recursive.
(Summary of changes)
$ git tag -a 1.2.1

接着將代碼合併回開發分支:

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff hotfix-1.2.1
Merge made by recursive.
(Summary of changes)

這裏一個特殊點在於,若是此時存在一個發佈分支,修復分支的變動須要合併到發佈分支中,而非開發分支。合併到發佈分支中,能夠最終將該修復經過發佈分支帶回到開發分支中。(若是開發分支也須要馬上修復該問題,沒法等到發佈分支合併回來,也能夠先將該變動安全的合併會發布分支)

$ git branch -d hotfix-1.2.1
Deleted branch hotfix-1.2.1 (was abbe5d6).
相關文章
相關標籤/搜索