第一次翻譯,輕噴,若有錯誤請在評論區指出,我會盡快修改。
如下是正文php
在這篇文章中,我將介紹一年前我爲個人一些項目(包括工做項目和私人項目)引入的開發模型,這個模型很是成功。我想寫這篇文章已經有一段時間了,可是一直沒有足夠的時間去認真地寫這篇文章,如今有這個機會了。我不會談論任何項目的細節,僅僅是談論關於分支策略和發佈管理。 git
有關Git與集中式源代碼管理系統相比的利弊的深刻討論,請參見這篇文章。這每每涉及不少爭論。做爲一名開發者,我愛Git賽過其餘一切工具。我曾經使用古老的CVS/Subversion,合併/分支一直被認爲有點可怕(「當心合併衝突,他們會咬人」),有些事情你只想經歷一次。shell
可是使用Git,這些操做很是方便和簡單,他們會成爲你工做流程的核心部分之一。例如,在CVS/Subversion手冊中,分支和合並第一次被討論是在後面的章節(高級用法),而在每一個Git手冊中,第3章(基礎)就進行了介紹。安全
因爲它的簡單性和重複性,分支和合並再也不是什麼可怕的東西。版本控制工具應該比任何其餘工具更有助於進行分支/合併。服務器
關於工具的討論就到此爲止,讓咱們進入開發模式吧。我在這裏將要介紹的模型本質上不過是一組過程,每一個團隊成員都必須遵循這些過程才能進入一個託管軟件開發過程。svn
咱們使用的倉庫設置和分支模型可以很好地工做,主要是由於有一個「真正」的中央倉庫。請注意,這個倉庫僅被視爲中央倉庫(因爲Git是DVCS,所以在技術層面上沒有中央倉庫)。 咱們將此倉庫稱origin,由於全部Git用戶都熟悉該名稱。工具
每一個開發者都從這個origin倉庫拉去和推送代碼。可是,除了集中推拉關係以外,每一個開發者還能夠從其餘同行那裏拉取修改,組成子團隊。例如,與兩個或多個開發者一塊兒開發一個比較複雜的新特性,將正在進行的工做提早推進到origin倉庫,這樣會頗有用。上面圖有Alice和Bob,Alice和David,Clair和David三個子團隊。加密
從技術上講,這不過是ALice定義了一個名爲Bob的指向Bob的倉庫的遠程倉庫,反之亦然。spa
在覈心方面,開發模型受到現有模型的極大啓發,中央倉庫有兩個無限生命週期的主分支。翻譯
每一個Git用戶都熟悉origin倉庫的master分支。與master分支平行的另外一個分支被稱爲develop。
咱們把origin/master當作用於生產環境中的源代碼的主分支。
origin/master中的源代碼老是表明了下一個發佈的版本。有些人將此稱爲「整合分支」。這是任何自動夜間構建的地方。
當開發分支中的源代碼到達一個穩定點並準備發佈時,全部的更改都應該以某種方式合併回主程序中,而後用一個發佈號進行標記。如何進行詳細處理將進一步討論。
所以,每次更改被合併到master分支時,就定義了一個新的生產版本。在這一點上,咱們是很是嚴肅的,因此從理論上講,咱們可使用Git鉤子腳本,在每次提交maser分支時候,在產品服務器上自動構建和回滾咱們的軟件。
接下來,咱們的開發模式使用各類輔助分支來幫助團隊成員之間的並行開發,方便追蹤新特性,準備生產發佈,幫助快速修復現線上產品問題。與主分支不一樣,這些分支老是具備有限的壽命時間,由於它們最終將被移除。
咱們可能使用的不一樣分支有:
每一個分支都有特定的用途,而且必須遵照嚴格的規則,即哪些分支能夠是它們的起始分支,哪些分支必須是它們的合併目標。咱們立刻來看看他們。
從技術角度看,這些分支毫不是「特殊」的。分支類型是根據咱們使用它們的方式來分類的。它們仍然是咱們熟悉的Git分支。
可能建立於:
develop
一定會合併到:
develop
分支命名約定:
除了master,develop,release-*,或 hotfix-*之外
特性分支(或有時稱爲主題分支)用於爲即將發佈或遙遠的未來版本開發的新特性。 當開始開發特性時,此時可能不知道將合併該特性的目標版本。 特性分支的本質是隻要特性在開發中就存在,可是最終會合並回到develop分支中(以確保將新功能添加到即將發佈的版本中)或丟棄(若是實驗使人失望)。
特性分支只存在與開發人員的倉庫,不存在於origin倉庫
$ git checkout -b myfeature develop // 建立並切換到「myfeature」分支
$ git checkout develop // 切換到「develop」分支 $ git merge --no-ff myfeature // 將新特性合併到「develop」分支 $ git branch -d myfeature // 刪除特性分支 $ git push origin develop // 推送變動
--no-ff使合併始終建立一個新的提交對象,即便合併能夠經過快進來執行。 這樣能夠避免丟失有關特性分支歷史存在的信息,並將全部添加了特性的提交組織在一塊兒。 比較:
在第二種狀況下,沒法從Git歷史記錄中看到哪些提交對象一塊兒實現了特性,您將不得不手動讀取全部日誌消息。 在第二種狀況下,還原整個功能(即一組提交)確實很頭疼,而若是使用--no-ff則很輕鬆不少。
固然,這將會產生一些額外的(空)提交,可是收益比成本大得多。
可能產生於
develop
必需要合併到
develop 和 master
分支命名規範
release-*
release分支支持一個新的生產版本的發行。他們容許最後幾分鐘的修改。此外,他們容許較小的錯誤修復和準備版本的元數據(版本號、構建日期等)。經過在發佈版本上執行這些操做,develop將作好發佈下一個大版本的準備。
當開發版本已經可以反映新版本特性的時候,就是將release分支從develop分支中分離出來的好時機。在這個時候,至少最新的針對最新發型版本進行構建的新特性都必需要合併回develop分支。全部針對將來版本的特性則不須要合併——它們必須等到release分支被分離後才能合併。
在準備一個release分支的時候就能夠爲這個版本進行命名了,不須要太早。直到那一刻,develop分支仍反映「下一版本」的變化,但直到分離分支開始,尚不清楚該「下一版本」是否最終變成0.3或1.0。肯定版本號是在準備一個release分支時開始的,並根據項目在版本號上的規則來決定。
發佈分支是從開發分支建立的。例如,假設1.1.5是當前的生產版本,咱們即將發佈一個大版本。開發的狀態已經爲「下一個版本」作好了準備,咱們已經決定這將變成1.2版(而不是1.1.6或2.0)。所以,咱們退出發行版,並給發佈分支一個反映新版本號的名稱:
$ git checkout -b release-1.2 develop // 切換到一個新分支 release-1.2 $ ./bump-version.sh 1.2 // 文件修改爲功,版本號 1.2 $ git commit -a -m "Bumped version number to 1.2"
在建立一個新的分支並切換到它以後,我會修改版本號。在這裏bump-version.sh
是一個虛構的shell腳本,它能夠更改工做副本中的一些文件,以反映新版本(固然也能夠手動更改——關鍵是一些文件發生更改),而後Bump版本被提交。
該新分支可能會保留一段時間,直到版本被明確的發佈後。在此期間,能夠在該分支中(而不是develop分支)進行bug修復。在此期間,嚴格禁止添加較大的新功能。它們必需要合併到develop分支中,在下一個大版本中發佈。
當release分支準備好發佈的時候,須要執行一些操做。首先,release分支合併到master分支(由於master分支的的每一次提交都是一個新版本,必定要記住)。接下來,master分支上的下一次提交須要進行標記,以便往後回顧歷史版本。最後,在release分支上所作的更改須要合併回develop分支,以便未來的版本也包含這些錯誤修復。
在Git中的前兩步
$ git checkout master // 切換到master分支 $ git merge --no-ff release-1.2 // 進行合併 $ git tag -a 1.2 // 打標籤
如今完成發佈,並作好了標記。
建議:您最好使用`-s`或`-u <key>`對標記加密簽名
爲了保存在release分支中作的修改,咱們須要將它合併回develop分支,所以,在Git中:
$ git checkout develop // 切換到develop分支 $ git merge --no-ff release-1.2 // 合併分支
這一步驟可能會致使合併衝突(咱們甚至可能會所以更改版本號)。若是這樣的話,修復後再次進行提交。
如今,咱們真的完成了release分支,而且能夠移除掉它了,由於咱們不再須要它了。
$ git branch -d release-1.2 // 刪除release-1.2分支
可能產生於
master
必須合併到
develop和master
分支命名規範
hotfix-*
hotfix分支很是相似於release分支,由於它也是爲了生產版本作準備,儘管是hotfix分支在計劃以外。它產生的緣由是生產版本存在問題,須要當即進行修復。當在生產版本中發現了一個嚴重bug時,能夠將hotfix從master分支上被標記過的相應地方分離出來。
本質上講,團隊成員的工做(在develop分支)仍能夠繼續進行,由另外一我的來準備快速的修復版本。
hotfix分支從master分支上建立。例如,版本1.2是當前發佈的生產版本,可是因爲存在bug而不穩定。可是develop分支還在修改也不穩定。咱們須要分離出一個hotfix分支,並修復這個問題:
$ git checkout -b hotfix-1.2.1 master // 建立hotfix-1.2.1並切換到該分支 $ ./bump-version.sh 1.2.1 // 執行shell攪拌 文件修改爲功 修改版本號 $ git commit -a -m "Bumped version number to 1.2.1" // 提交分支
不要忘記在分支結束後增長版本號!
而後在一個或多個提交中修復bug。
$ git commit -m "Fixed severe production problem"
完成後,須要將bug修復合回到master分支,可是咱們也須要合併到develop分支,以確保bug修復包含在下一個發行版本中。這和釋放release分支作法相似。
$ git checkout master // 切換到master分支 $ git merge --no-ff hotfix-1.2.1 // 合併分支 $ git tag -a 1.2.1 // 打標籤
建議:您最好使用`-s`或`-u <key>`對標記加密簽名
接下來,將bug修復合併到develop分支
$ git checkout develop // 切換到develop分支 $ git merge --no-ff hotfix-1.2.1 // 合併分支
這裏有一個例外,當release分支還存在,hotfix分支須要到release分支,而不是develop分支 。當release分支完成後,bug修復合併到release分支會讓bug修復也包含到develop分支中(若是develop分鐘須要當即修復這個bug,而且不能等待release分支完成,你也能夠安全地將bug修復合併到develop中)。
最後移除掉這個臨時的分支:
$ git branch -d hotfix-1.2.1 // 刪除分支
雖然這個分支模式並無真正使人驚訝的新事物,但這個帖子開頭的「大圖片」在咱們的項目中是很是有用的。它造成了一個優雅的心理模型,易於團隊成員理解分支和發佈過程。
這裏提供了一個高質量的PDF版本的數字.你能夠隨時把它掛在牆上,以供快速參考。