- 簡(jiǎn)介
Gitflow工作流程圍繞項(xiàng)目發(fā)布定義了嚴(yán)格的分支模型。盡管它比Feature Branch Workflow更復(fù)雜一些,但它也為管理更大規(guī)模的項(xiàng)目提供了堅(jiān)實(shí)的框架。
與Feature Branch Workflow比起來(lái),Gitflow流程并沒(méi)有增加任何新的概念或命令。其特色在于,它為不同的分支分配了非常明確的角色,并且定義了使用場(chǎng)景和用法。除了用于功能開(kāi)發(fā)的分支,它還使用獨(dú)立的分支進(jìn)行發(fā)布前的準(zhǔn)備、記錄以及后期維護(hù)。當(dāng)然,你還是能充分利用Feature Branch Workflow的好處:拉拽請(qǐng)求(Pull Request)、隔離的試驗(yàn)以及更高效率的合作。
- 工作原理
流程仍然使用一個(gè)中央代碼倉(cāng)庫(kù),它是所有開(kāi)發(fā)者的信息交流中心。跟其他的工作流程一樣,開(kāi)發(fā)者在本地完成開(kāi)發(fā),然后再將分支代碼推送到中央倉(cāng)庫(kù)。唯一不同的是項(xiàng)目中分支的結(jié)構(gòu)。
用于記錄歷史的分支
Gitflow使用兩個(gè)分支來(lái)記錄項(xiàng)目開(kāi)發(fā)的歷史,而不是使用單一的master分支。在Gitflow流程中,master只是用于保存官方的發(fā)布?xì)v史,而develop分支才是用于集成各種功能開(kāi)發(fā)的分支。使用版本號(hào)為master上的所有提交打標(biāo)簽(tag)也很方便。

事實(shí)上,Gitflow流程就是圍繞這兩個(gè)特點(diǎn)鮮明的分支展開(kāi)的。
用于功能開(kāi)發(fā)的分支
每一個(gè)新功能的開(kāi)發(fā)都應(yīng)該各自使用獨(dú)立的分支。為了備份或便于團(tuán)隊(duì)之間的合作,這種分支也可以被推送到中央倉(cāng)庫(kù)。但是,在創(chuàng)建新的功能開(kāi)發(fā)分支時(shí),父分支應(yīng)該選擇develop(而不是master)。當(dāng)功能開(kāi)發(fā)完成時(shí),改動(dòng)的代碼應(yīng)該被合并(merge)到develop分支。功能開(kāi)發(fā)永遠(yuǎn)不應(yīng)該直接牽扯到master。

用于發(fā)布的分支
一旦develop分支積聚了足夠多的新功能(或者預(yù)定的發(fā)布日期臨近了),你可以基于develop分支建立一個(gè)用于產(chǎn)品發(fā)布的分支。這個(gè)分支的創(chuàng)建意味著一個(gè)發(fā)布周期的開(kāi)始,也意味著本次發(fā)布不會(huì)再增加新的功能——在這個(gè)分支上只能修復(fù)bug,做一些文檔工作或者跟發(fā)布相關(guān)的任務(wù)。在一切準(zhǔn)備就緒的時(shí)候,這個(gè)分支會(huì)被合并入master,并且用版本號(hào)打上標(biāo)簽。另外,發(fā)布分支上的改動(dòng)還應(yīng)該合并入develop分支——在發(fā)布周期內(nèi),develop分支仍然在被使用(一些開(kāi)發(fā)者會(huì)把其他功能集成到develop分支)。使用專門的一個(gè)分支來(lái)為發(fā)布做準(zhǔn)備的好處是,在一個(gè)團(tuán)隊(duì)忙于當(dāng)前的發(fā)布的同時(shí),另一個(gè)團(tuán)隊(duì)可以繼續(xù)為接下來(lái)的一次發(fā)布開(kāi)發(fā)新功能。

用于維護(hù)的分支
發(fā)布后的維護(hù)工作或者緊急問(wèn)題的快速修復(fù)也需要使用一個(gè)獨(dú)立的分支。這是唯一一種可以直接基于master創(chuàng)建的分支。一旦問(wèn)題被修復(fù)了,所做的改動(dòng)應(yīng)該被合并入master和develop分支(或者用于當(dāng)前發(fā)布的分支)。在這之后,master上還要使用更新的版本號(hào)打好標(biāo)簽。

- 開(kāi)發(fā)實(shí)例
創(chuàng)建develop分支

第一步是給默認(rèn)的master配備一個(gè)develop分支。一種簡(jiǎn)單的做法是:讓一個(gè)開(kāi)發(fā)者在本地建立一個(gè)空的develop分支,然后把它推送到服務(wù)器。
develop分支將包含項(xiàng)目的所有歷史,而master會(huì)是一個(gè)縮減版本?,F(xiàn)在,其他開(kāi)發(fā)者應(yīng)該克?。╟lone)中央倉(cāng)庫(kù),并且為develop創(chuàng)建一個(gè)追蹤分支。
A和B開(kāi)發(fā)新功能

分別開(kāi)發(fā)新功能開(kāi)始。他們倆各自建立了自己的分支。注意,他們?cè)趧?chuàng)建分支時(shí),父分支不能選擇master,而要選擇develop。
他們倆都在自己的功能開(kāi)發(fā)分支上開(kāi)展工作。通常就是這種Git三部曲:edit,stage,commit:
A把他的功能開(kāi)發(fā)好了

在提交過(guò)幾次代碼之后,A覺(jué)得他的功能做完了。如果她所在的團(tuán)隊(duì)使用“拉拽請(qǐng)求”,此刻便是一個(gè)合適的時(shí)機(jī)——她可以提出一個(gè)將她所完成的功能合并入develop分支的請(qǐng)求。要不然,她可以自行將她的代碼合并入本地的develop分支,然后再推送到中央倉(cāng)庫(kù),像這樣:
第一條命令確保了本地的develop分支擁有最新的代碼——這一步必須在將功能代碼合并之前做!注意,新開(kāi)發(fā)的功能代碼永遠(yuǎn)不能直接合并入master。必要時(shí),還需要解決在代碼合并過(guò)程中的沖突。
A開(kāi)始準(zhǔn)備一次發(fā)布

盡管B還在忙著開(kāi)發(fā)他的功能,A卻可以開(kāi)始準(zhǔn)備這個(gè)項(xiàng)目的第一次正式發(fā)布了。類似于功能開(kāi)發(fā),她使用了一個(gè)新的分支來(lái)做產(chǎn)品發(fā)布的準(zhǔn)備工作。在這一步,發(fā)布的版本號(hào)也最初確定下來(lái)。
這個(gè)分支專門用于發(fā)布前的準(zhǔn)備,包括一些清理工作、全面的測(cè)試、文檔的更新以及任何其他的準(zhǔn)備工作。它與用于功能開(kāi)發(fā)的分支相似,不同之處在于它是專為產(chǎn)品發(fā)布服務(wù)的。
一旦A創(chuàng)建了這個(gè)分支并把它推向中央倉(cāng)庫(kù),這次產(chǎn)品發(fā)布包含的功能也就固定下來(lái)了。任何還處于開(kāi)發(fā)狀態(tài)的功能只能等待下一個(gè)發(fā)布周期。
A完成了發(fā)布

一切準(zhǔn)備就緒之后,A就要把發(fā)布分支合并入master和develop分支,然后再將發(fā)布分支刪除。注意,往develop分支的合并是很重要的,因?yàn)殚_(kāi)發(fā)人員可能在發(fā)布分支上修復(fù)了一些關(guān)鍵的問(wèn)題,而這些修復(fù)對(duì)于正在開(kāi)發(fā)中的新功能是有益的。再次提醒一下,如果A所在的團(tuán)隊(duì)強(qiáng)調(diào)代碼評(píng)審(Code Review),此時(shí)非常適合提出這樣的請(qǐng)求。
git checkout master
git merge release-0.1
git push
git checkout develop
git merge release-0.1
git push
git branch -d release-0.1
發(fā)布分支扮演的角色是功能開(kāi)發(fā)(develop)與官方發(fā)布(master)之間的一個(gè)緩沖。無(wú)論什么時(shí)候你把一些東西合并入master,你都應(yīng)該隨即打上合適的標(biāo)簽。
git tag -a 0.1 -m"Initial public release" master
git push --tags
Git支持鉤子(hook)的功能,也就是說(shuō),在代碼倉(cāng)庫(kù)里某些特定的事件發(fā)生的時(shí)候,可以執(zhí)行一些預(yù)定義的腳本。因此,一種可行的做法是:在服務(wù)器端配置一個(gè)鉤子,當(dāng)你把master推送到中央倉(cāng)庫(kù)或者推送標(biāo)簽時(shí),Git服務(wù)器能為產(chǎn)品發(fā)布進(jìn)行一次自動(dòng)的構(gòu)建。
用戶發(fā)現(xiàn)了一個(gè)bug

當(dāng)一次發(fā)布完成之后,A便回去與B一起開(kāi)發(fā)其他功能了。突然,某個(gè)用戶提出抱怨說(shuō)當(dāng)前發(fā)布的產(chǎn)品里有一個(gè)bug。為了解決這個(gè)問(wèn)題,A(或者B)基于master創(chuàng)建了一個(gè)用于維護(hù)的分支。她在這個(gè)分支上修復(fù)了那個(gè)bug,然后把改動(dòng)的代碼直接合并入master。
git checkout -b issue-#001 master
# Fix the bug
git checkout master
git merge issue-#001
git push
跟用于發(fā)布的分支一樣,在維護(hù)分支上的改動(dòng)也需要合并入develop分支,這一點(diǎn)是很重要的!因此,小馬務(wù)必不能忘了這一步。隨后,她就可以將維護(hù)分支刪除。
git checkout develop
git merge issue-#001
git push
git branch -d issue-#001
上面介紹的是git flow 的詳細(xì)過(guò)程,但是這樣開(kāi)發(fā)起來(lái)會(huì)接的是否麻煩,git flow對(duì)其進(jìn)行了封裝簡(jiǎn)化。
使用
初始化: git flow init
開(kāi)始新Feature: git flow feature start MYFEATURE
Publish一個(gè)Feature(也就是push到遠(yuǎn)程): git flow feature publish MYFEATURE
獲取Publish的Feature: git flow feature pull origin MYFEATURE
完成一個(gè)Feature: git flow feature finish MYFEATURE
開(kāi)始一個(gè)Release: git flow release start RELEASE [BASE]
Publish一個(gè)Release: git flow release publish RELEASE
發(fā)布Release: git flow release finish RELEASE
別忘了git push --tags開(kāi)始一個(gè)Hotfix: git flow hotfix start VERSION [BASENAME]
發(fā)布一個(gè)Hotfix: git flow hotfix finish VERSION
git flow init
這個(gè)命令會(huì)進(jìn)行一些默認(rèn)的配置,可以自動(dòng)創(chuàng)建上面介紹的所有分支:master、develop、feature、relase、hotfix等分支。
完成后當(dāng)前所在分支就變成 develop. 任何開(kāi)發(fā)都必須從 develop 開(kāi)始:
當(dāng)進(jìn)行新功能開(kāi)發(fā)的時(shí)候:
git flow feature start some_awesome_feature
完成功能開(kāi)發(fā)之后:
git flow feature finish some_awesome_feature
該命令將會(huì)把feature/some_awesome_feature合并到develope分支,然后刪除功能(feature)分支。
將一個(gè) feature 分支推到遠(yuǎn)程服務(wù)器
git flow feature publish some_awesome_feature 或者 git push origin feature/some_awesome_feature
當(dāng)你的功能點(diǎn)都完成時(shí)(需要發(fā)布新版本了),就基于develop創(chuàng)建一個(gè)發(fā)布(release)分支。
git flow release start v0.1.0
當(dāng)你在完成(finish)一個(gè)發(fā)布分支時(shí),它會(huì)把你所作的修改合并到master分支,同時(shí)合并回develop分支,所以,你不需要擔(dān)心你的master分支比develop分支更加超前。
當(dāng)系統(tǒng)出現(xiàn)問(wèn)題的時(shí)候,需要進(jìn)行緊急修改的時(shí)候,就好基于master創(chuàng)建一個(gè)維護(hù)(hotfix)分支。
git flow hotfix start v0.1.0
當(dāng)你在完成(finish)一個(gè)維護(hù)分支時(shí),它會(huì)把你所作的修改合并到master分支,同時(shí)合并回develop分支。
轉(zhuǎn)載博客:https://www.cnblogs.com/lcngu/p/5770288.html