代碼管理是整個項目管理週期中重要的一環,而代碼管理是始終圍繞版本發佈流程而制定的,今天討論的Gitflow就是一種版本發佈方案。html
Gitflow是一個基於feature分支管理的版本發佈方案。它是由荷蘭程序猿Vincent Driessen設計研發,開源項目地址gitflow-avh。git
大體流程是:github
若線上發現嚴重bug,需走hotfix流程。bash
下圖是Gitflow發佈的經典圖片,直觀反映了Gitflow發佈的全流程。ide
它的特色是能靈活的根據實際需求發佈相應版本,較好的支持並行開發,歷史版本用tag進行維護。工具
下面將介紹如何使用Gitflow命令完成上述版本發佈,一條Gitflow指令可能對應了一系列git命令,爲的是規範化開發流程,提升代碼管理效率。gitlab
brew install git-flow
複製代碼
brew表示Homebrew,它是mac平臺經常使用的包管理器,沒有安裝則需先安裝,安裝可參考Mac OS下brew的安裝和使用。測試
先將遠程倉庫克隆到本地。fetch
git clone <project_url>
複製代碼
各類初始化Gitflow配置。ui
git flow init
複製代碼
命令行會提示你是否修改Gitflow提供的默認分支前綴。不一樣場景的分支前綴不一樣,默認狀況下分支前綴是這樣的:
場景 | 分支前綴 |
---|---|
新功能 | feature |
預發佈 | release |
熱修復 | hotfix |
打tag | 空 |
分支前綴的做用是區分不一樣分支的使用場景,同時當你使用Gitflow命令時就不需手動添加分支前綴了,Gitflow會幫你加上。
好比開發新功能需建立一個feature分支,名爲gitworkflow,使用下面的代碼將會建立一個名爲feature/gitworkflow本地分支。
git flow feature start gitworkflow
複製代碼
一般狀況下不須要修改默認的命名前綴,只需加上-d就可跳過修改命名階段。
git flow init -d
複製代碼
一般來講,一種場景的完整生命週期應至少包含如下幾種行爲:
咱們首先以feature場景爲例,看看如何完成工做流。
新功能開始開發前,需準備好開發分支。
git flow feature start <feature_name>
複製代碼
執行上面的命令將會在本地建立名爲<feature_name>的分支,並切換到該分支,並且不論當前所處哪一個分支都是基於develop分支建立,至關於執行了下面的git的命令。
git checkout -b feature/<feature_name> develop
複製代碼
須要注意基於的是本地的develop分支,執行此命令前通常須要拉取最新的遠程代碼。
在本地開發完成新功能並commit後,須要將本地代碼push到遠程倉庫。
git flow feature publish <feature_name>
複製代碼
這行指令作了三件事。
轉換成git命令就是下面的樣子:
git push origin feature/<feature_name>
git push --set-upstream origin feature/<feature_name>
git push origin
複製代碼
注意:
若是已經執行過publish後又有新的代碼需push,再次執行將報錯,由於它始終會試圖建立一個遠程分支。此時需執行正常的push命令git push origin
。
當功能開發完畢後就將進入測試階段,此時需將一個或多個feature分支統一合併到develop分支。
git flow feature finish <feature_name>
複製代碼
這行指令也作了三件事。
等價於執行下面的git命令:
git checkout develop
git merge feature/<feature_name>
git branch -d feature/<feature_name>
複製代碼
說到merge,就不得不提merge採用的策略,咱們使用git merge命令時默認(主分支沒有新的提交、沒有衝突等狀況)使用的是fast-forward模式(如下簡稱ff),即只移動HEAD指針而不會生成提交記錄。
而Gitflow稍有不一樣,默認狀況下它會檢查本次merge有多少次commit記錄,若是僅有一條採用ff模式,若是超過一條則採用no-ff模式,no-ff模式下會多生成一條merge的commit記錄。
這樣作的好處是當只有一條提交記錄時若是生成一條merge記錄實際上會複雜化代碼記錄的管理;當有多條commit記錄時生成的一個merge記錄,能夠方便的進行代碼回退和記錄檢查。
回到finish主題,若是merge時發生了衝突,則在第二步merge時終止流程,即不會再刪除本地分支。但當前已處於develop分支,待本地衝突解決並commit後,從新執行git flow feature finish <feature_name>
便可完成finish流程。
細心的同窗能夠已經發現finish還有兩件事沒作。
也就是還需執行
git push origin develop
git push origin :feature/<feature_name>
複製代碼
另外,finish指令支持三個附加參數。
因此若是想連同遠程分支一併刪除可以使用。
git flow feature finish -F <feature_name>
複製代碼
若是你對feature指令感興趣,下面是其支持的全部指令。
git flow feature [list] [-v]
git flow feature start [-F] <name> [<base>]
git flow feature finish [-rFk] <name|nameprefix>
git flow feature publish <name>
git flow feature track <name>
git flow feature diff [<name|nameprefix>]
git flow feature rebase [-i] [<name|nameprefix>]
git flow feature checkout [<name|nameprefix>]
git flow feature pull <remote> [<name>]
複製代碼
上面的內容以feature場景爲例,詳細的分析了整個新功能執行流程。
下面咱們再來看release場景,連同以前的feature場景,整個流程以下。
當新功能開發完畢,將進入測試階段,此時須要基於develop分支拉出release分支進行集成測試,也有將release場景做爲預發佈環境進行測試的,即feature場景已完成常規測試,在這種狀況下,通常而言release只有少數改動。在這裏咱們先不討論項目流程問題。
使用start指令開啓一個release場景,一般以版本號命令,咱們以v2.0爲例:
git flow release start v2.0
複製代碼
此命令會基於本地的develop分支建立一個release/v2.0分支,並切換到這個分支上。
爲了讓其餘協同人員也能看到此分支,須要將其發佈出去。
git flow release publish v2.0
複製代碼
以上和feature場景十分相似。
待測試經過須要發佈正式版:
git flow release finish v2.0
複製代碼
這一步作的動做有點多,大體是:
若是merge產生衝突不會終止流程,只是不會將本地的release分支刪除,待解決完衝突後需再次執行finish指令。
另外須要注意的是,若是本地還有未finish的release分支,將不容許使用start指令開啓新的release分支,這一點是對並行發佈的一個限制。
release finish只是完成了本地代碼的一系列操做,還須要同步到遠程倉庫。
git push origin develop
git push origin master
git push origin v2.0
複製代碼
或者使用下面的命令推送全部的分支和tag。
git push origin --all
git push origin --tags
複製代碼
當tag打完,也表示正式版本發佈出去了,若是此時在線上發現了嚴重的bug,須要進行緊急修復,流程以下:
此時咱們假設版本號變爲v2.0-patch。
git flow hotfix start v2.0-patch
複製代碼
這將建立一個hotfix/v2.0本地分支並切換到該分支。 hotfix沒有publish指令,認爲hotfix應該是個小範圍改動,不須要其餘協同人員參與。
待本地修改結束commit後,執行finish指令。
git flow hotfix finish v2.0-patch
複製代碼
按照Gitflow工做流,它會執行下面的任務,與release基本一致。
在實際開發中發現,Gitflow命令有點長,容易敲錯。好比git flow feature start <name>
,所以我寫了一個簡化的指令,經過它能夠這樣寫./gitflow -fs <name>
。也就是取Gitflow指令關鍵字的首字母組合,爲新的指令集。
詳情參見Github gitflow.sh。
Sourcetree徹底支持Gitflow的全部操做,若是你習慣於使用圖形化工具管理你的代碼,能夠直接使用Sourcetree的Gitflow功能。
瞭解了上面的命令,這個圖形化界面基本就都能見名知意了。
與Gitflow類似的代碼管理工做流還有,Github flow和Gitlab flow。
Github flow是簡化版的Gitflow,它使用master和feature來管理代碼,它只有一個長期分支,就是master。Gitlab flow更關注代碼的持續集成,一個版本須要建立測試環境、預覽環境、生產環境的分支,最終彙總到stable branch用於發佈,感興趣的小夥伴能夠自行了解。
下表是筆者對三者特色的理解:
項目 | Gitflow | Github flow | Gitlab flow |
---|---|---|---|
特色 | 基於master和develop分支 | 基於master分支和PR | 基於master分支,使用「上游優先」原則 |
易用性 | 複雜,需結合Gitflow工具 | 簡單 | 通常 |
並行開發 | 簡單 | 難 | 通常 |
側重點 | 靈活性、多feature管理/版本管理 | 分支維護效率 | 持續集成 |
歷史版本維護 | tag | tag或stable branch | stable branch |
實際上Gitflow的發佈流程一直飽受爭議,反對者認爲feature開發週期通常較長,也就是可能在較長時間內不能合併到主幹分支,這不利於持續集成,且在合併到主幹時可能產生大量衝突,參看這篇Gitflow有害論。
但筆者認爲若是你正在參與一個企業級的項目,一個版本將要上線的features可能因各類緣由變更或下線,此時若是沒有獨立的feature分支而所有在主幹分支,將極難處理代碼的回滾和保護;換個角度說,merge衝突也能夠經過其餘方式規避,好比良好的代碼分層、事先約定好跨模塊通訊的接口等。
從持續集成的角度來講,因爲Gitflow管理的分支類型較多,不該全部分支都參與持續集成,可結合實際場景選擇開啓持續集成的分支類型,好比master和release。
最後,沒有最好的方案,只有最適合的方案,實際的項目管理過程當中應根據不一樣工做流的特色選擇適合的方案便可。
若是你還有什麼疑問,歡迎留言探討。