介紹一個成功的 Git 分支模型 Release 分支


英文原文:

http://nvie.com/posts/a-successful-git-branching-model/

中文版:

在這篇文章中,我提出一個開發模型。我已經將這個開發模型引入到我所有的項目里(論在工作還是私人)已經一年有余,並且它被證明是非常成功的。我打算寫這些已經很久了,但我一直找不到時間來做,現在終於有時間了。我不會講任何項目的具體細節,僅是關於分支策略和釋放管理相關內容。

介紹一個成功的 Git 分支模型

它主要體現了Git對我們源代碼版本的管理。

為何是Git?

對於Git與其他集中式代碼管理工具相比的優缺點的全面討論,請參見這里。這樣的爭論總是喋喋不休。作為一個開發者,與現今的其他開發工具相比較,我更喜歡Git。Git真得改變了開發者對於合並和分支的思考。我曾經使用經典的CVS/Subversion,然而每次的合並/分支和其他行為總讓人擔驚受怕(“小心合並里的沖突,簡直要命!”)。

但是對於Git來說,這些行為非常簡單和搞笑,它們被認為是日常工作中的核心部分。例如,在很多CVS/Subversion書里,分支與合並總是在后面的章節中被討論(對於高級用戶使用),然而在每個Git書中,在第3章就已經完全涵蓋了(作為基礎)。

簡單和重復的特性帶來的結果是:分支與合並不再是什么可以害怕的東西。分支/合並被認為對於版本管理工具比其他功能更重要。

關於工具,不再多說,讓我們直接看開發模型吧。這個模型並不是如下模型:在管理軟件開發進度方面,面對每個開發過程,每個隊員必須按一定次序開發。

分布式而非集中式

對於這種分支模型,我們設置了一個版本庫,它運轉良好,這是一個事實上 版本庫。不過請注意,這個版本庫只是被認為是中心版本庫(因為Git是一個分布式版本管理系統,從技術上來講,並沒有一個中心版本庫)。我們將把這個版本庫稱為原始庫,這個名字對所有的Git用戶來說都很容易理解。

介紹一個成功的 Git 分支模型

每個開發者都對origin庫拉代碼和提交代碼。但是除了集中式的存取代碼關系,每個開發者也可以從子團隊的其他隊友那里獲得代碼版本變更。例如,對於2個或多個開發者一起完成的大版本變更,為了防止過早地向origin庫提交工作內容,這種機制就變得非常有用。在上述途中,有如下子團隊:Alice和Bob,Alice和David,Clair和David。

從技術上將,這意味着,Alice創建了一個Git的遠程節點,而對於Bob,該節點指向了Bob的版本庫,反之亦然。

主分支

介紹一個成功的 Git 分支模型

在核心部分,研發模型很大程度上靠其他現有模型支撐的。中心庫有2個可一直延續的分支:

  • master分支
  • develop分支

每個Git用戶都要熟悉原始的master分支。與master分支並行的另一個分支,我們稱之為develop分支。

我們把原始庫/master庫認作為主分支,HEAD的源代碼存在於此版本中,並且隨時都是一個預備生產狀態。

輔助性分支

我們的開發模型使用了各種輔助性分支,這些分支與關鍵分支(master和develop)一起,用來支持團隊成員們並行開發,使得易於追蹤功能,協助生產發布環境准備,以及快速修復實時在線問題。與關鍵分支不同,這些分支總是有一個有限的生命期,因為他們最終會被移除。

我們用到的分支類型包括:

  • 功能分支
  • 發布分支
  • 熱修復分支

每一種分支有一個特定目的,並且受限於嚴格到規則,比如:可以用哪些分支作為源分支,哪些分支能作為合並目標。我們馬上將進行演練。

從技術角度來看,這些分支絕不是特殊分支。分支的類型基於我們使用的方法來進行分類。它們理所當然是普通的Git分支。

功能分支

介紹一個成功的 Git 分支模型

可能是develop分支的分支版本,最終必須合並到develop分支中。

分支命名規則:除了master、develop、release-*、orhotfix-*之外,其他命名均可。

功能分支(有時被稱為topic分支)通常為即將發布或者未來發布版開發新的功能。當新功能開始研發,包含該功能的發布版本在這個還是法確定發布時間的。功能版本的實質是只要這個功能處於開發狀態它就會存在,但是最終會或合並到develop分支(確定將新功能添加到不久的發布版中)或取消(譬如一次令人失望的測試)。

功能分支通常存在於開發者的軟件庫,而不是在源代碼庫中。

創建一個功能分支

開始一項功能的開發工作時,基於develop創建分支。

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

合並一個功能到develop分支

完成的功能可以合並進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標志導致合並操作創建一個新commit對象,即使該合並操作可以fast-forward。這避免了丟失這個功能分支存在的歷史信息,將該功能的所有提交組合在一起。 比較:

介紹一個成功的 Git 分支模型

后一種情況,不可能從Git歷史中看到哪些提交一起實現了一個功能——你必須手工閱讀全部的日志信息。如果對整個功能進行回退 (比如一組提交),后一種方式會是一種真正頭痛的問題,而使用no-ffflag的情況則很容易.

是的,它會創建一個新的(空)提交對象,但是收益遠大於開銷。

不幸的是,我還沒找到一種方法,讓no-ff時作為合並操作的默認選項,但它應該是可行的。

Release 分支

Release分支可能從develop分支分離而來,但是一定要合並到develop和master分支上,它的習慣命名方式為:release-*。

Release分支是為新產品的發布做准備的。它允許我們在最后時刻做一些細小的修改。他們允許小bugs的修改和准備發布元數據(版本號,開發時間等等)。當在Release分支完成這些所有工作以后,對於下一次打的發布,develop分支接收features會更加明確。

從develop分支創建新的Release分支的關鍵時刻是develop分支達到了發布的理想狀態。至少所有這次要發布的features必須在這個點及時合並到develop分支。對於所有未來准備發布的features必須等到Release分支創建以后再合並。

在Release分支創建的時候要為即將發行版本分配一個版本號,一點都不早。直到那時,develop分支反映的變化都是為了下一個發行版,但是在Release分支創建之前,下一個發行版到底叫0.3還是1.0是不明確的。這個決定是在Release分支創建時根據項目在版本號上的規則制定的。

創建一個release分支

Release分支是從develop分支創建的。例如,當前產品的發行版本號為1.1.5,同事我們有一個大的版本即將發行。develop 分支已經為下次發行做好了准備,我們得決定下一個版本是1.2(而不是1.1.6或者2.0)。所以我們將Release分支分離出來,給一個能夠反映新版本號的分支名。

$ 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分支上)。在這里嚴格禁止增加大的新features。他們必須合並到develop分支上,然后等待下一次大的發行版。

完成一個release分支

當一個release分支准備好成為一個真正的發行版的時候,有一些工作必須完成。首先,release分支要合並到master上(因為每一次提交到master上的都是一個新定義的發行版,記住)。然后,提交到master上必須打一個標簽,以便以后更加方便的引用這個歷史版本。最后,在release分支上的修改必須合並到develop分支上,以便未來發行版也包含這些bugs的修復。

在Git中的前兩步是:

$ 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

發行版現在已經完成,為以后引用打上標簽。

編輯:你可能也想使用The-sor-u flags來標記你的標簽。

為了是修改保持在release分支上,我們需要合並這些到develop分支上去,在Git上:

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

這個步驟可能會導致合並沖突(可能由於改變版本號更是如此)。如果是這樣,修復它然后提交。

現在我們真正的完成了,這個release分支將被刪除,因為我們不再需要它了。

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

熱修復分支

介紹一個成功的 Git 分支模型

可以基於master分支,必須合並回develop和master分支。
分支名約定:hotfix-*

熱修復分支與發布分支很相似,他們都為新的生成環境發布做准備,盡管這是未經計划的。他們來自生產環境的處於異常狀態壓力。當生成環境驗證缺陷必須馬上修復是,熱修復分支可以基於master分支上對應與線上版本的tag創建。

其本質是團隊成員(在develop分支上)的工作可以繼續,而另一個人准備生產環境的快速修復。

創建修補bug分支

hotfix branch(修補bug分支)是從Master分支上面分出來的。例如,1.2版本是當前生產環境的版本並且有bug。但是開發分支(develop)變化還不穩定。我們需要分出來一個修補bug分支(hotfix branch)來解決這種情況。

$ 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(-)

分支關閉的時侯不要忘了更新版本號(bump The version)

然后,修復bug,一次提交或者多次分開提交。

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

完成一個hotfix分支

完成一個bugfix之后,需要把butfix合並到master和develop分支去,這樣就可以保證修復的這個bug也包含到下一個發行版中。這一點和完成release分支很相似。

首先,更新master並對release打上tag:

$ 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

編輯:你可能也會想使用 -sor-u 參數來對你的tag進行加密

下一步,把bugfix添加到develop分支中:

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

規則的一個例外是: 如果一個release分支已經存在,那么應該把hotfix合並到這個release分支,而不是合並到develop分支。當release分支完成后, 將bugfix分支合並回release分支也會使得bugfix被合並到develop分支。(如果在develop分支的工作急需這個bugfix,等不到release分支的完成,那你也可以把bugfix合並到develop分支)

最后,刪除臨時分支:

$ git branch -d hotfix-1.2.1
DeleTED branch hotfix-1.2.1 (was abbe5d6).

摘要

盡管這個分支模型沒有任何震撼的新東西, 文章開頭的圖表在我們的項目中表現出驚人的實用性。它形成了一個優雅的思維模型,易於領悟並使團隊成員發展出對分支和發布過程的共同理解。

這里提供一份高質量PDF格式圖表。去吧,把它掛載牆上以便能隨時快速參考。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM