作者:阮一峰
原文出處:http://www.ruanyifeng.com/blog/2015/12/git-workflow.html
Git 作為一個源碼管理系統(tǒng)礁鲁,不可避免涉及到多人協(xié)作。
協(xié)作必須有一個規(guī)范的工作流程,讓大家有效地合作梅屉,使得項目井井有條地發(fā)展下去瑟押。"工作流程"在英語里,叫做"workflow"或者"flow"奉芦,原意是水流,比喻項目像水流那樣剧蹂,順暢声功、自然地向前流動,不會發(fā)生沖擊宠叼、對撞减噪、甚至漩渦。
本文介紹三種廣泛使用的工作流程:
- Git flow
- Github flow
- Gitlab flow
如果你對Git還不是很熟悉车吹,可以先閱讀下面的文章筹裕。
一、功能驅(qū)動
本文的三種工作流程窄驹,有一個共同點:都采用"功能驅(qū)動式開發(fā)"(Feature-driven development朝卒,簡稱FDD)。
它指的是乐埠,需求是開發(fā)的起點抗斤,先有需求再有功能分支(feature branch)或者補丁分支(hotfix branch)。完成開發(fā)后丈咐,該分支就合并到主分支瑞眼,然后被刪除。
二棵逊、Git flow
最早誕生伤疙、并得到廣泛采用的一種工作流程,就是Git flow 辆影。
2.1 特點
它最主要的特點有兩個徒像。
首先,項目存在兩個長期分支蛙讥。
- 主分支master
- 開發(fā)分支develop
前者用于存放對外發(fā)布的版本锯蛀,任何時候在這個分支拿到的,都是穩(wěn)定的分布版次慢;后者用于日常開發(fā)旁涤,存放最新的開發(fā)版翔曲。
其次,項目存在三種短期分支劈愚。
- 功能分支(feature branch)
- 補丁分支(hotfix branch)
- 預(yù)發(fā)分支(release branch)
一旦完成開發(fā)部默,它們就會被合并進develop
或master
,然后被刪除造虎。
Git flow 的詳細介紹傅蹂,請閱讀我翻譯的中文版《Git 分支管理策略》。
2.2 評價
Git flow的優(yōu)點是清晰可控算凿,缺點是相對復(fù)雜份蝴,需要同時維護兩個長期分支。大多數(shù)工具都將master
當(dāng)作默認(rèn)分支氓轰,可是開發(fā)是在develop
分支進行的婚夫,這導(dǎo)致經(jīng)常要切換分支,非常煩人署鸡。
更大問題在于案糙,這個模式是基于"版本發(fā)布"的,目標(biāo)是一段時間以后產(chǎn)出一個新版本靴庆。但是时捌,很多網(wǎng)站項目是"持續(xù)發(fā)布",代碼一有變動炉抒,就部署一次奢讨。這時,master
分支和develop
分支的差別不大焰薄,沒必要維護兩個長期分支拿诸。
三、Github flow
Github flow 是Git flow的簡化版塞茅,專門配合"持續(xù)發(fā)布"亩码。它是 Github.com 使用的工作流程。
3.1 流程
它只有一個長期分支野瘦,就是master
描沟,因此用起來非常簡單。
官方推薦的流程如下缅刽。
第一步:根據(jù)需求啊掏,從master
拉出新分支,不區(qū)分功能分支或補丁分支衰猛。
第二步:新分支開發(fā)完成后,或者需要討論的時候刹孔,就向master
發(fā)起一個pull request(簡稱PR)啡省。
第三步:Pull Request既是一個通知娜睛,讓別人注意到你的請求,又是一種對話機制卦睹,大家一起評審和討論你的代碼畦戒。對話過程中,你還可以不斷提交代碼结序。
第四步:你的Pull Request被接受障斋,合并進master
,重新部署后徐鹤,原來你拉出來的那個分支就被刪除垃环。(先部署再合并也可。)
3.2 評價
Github flow 的最大優(yōu)點就是簡單返敬,對于"持續(xù)發(fā)布"的產(chǎn)品遂庄,可以說是最合適的流程。
問題在于它的假設(shè):master
分支的更新與產(chǎn)品的發(fā)布是一致的劲赠。也就是說涛目,master
分支的最新代碼凛澎,默認(rèn)就是當(dāng)前的線上代碼。
可是炭晒,有些時候并非如此,代碼合并進入master
分支怜庸,并不代表它就能立刻發(fā)布嘉栓。比如奠支,蘋果商店的APP提交審核以后尔崔,等一段時間才能上架轴捎。這時尺碰,如果還有新的代碼提交,master
分支就會與剛發(fā)布的版本不一致固耘。另一個例子是题篷,有些公司有發(fā)布窗口,只有指定時間才能發(fā)布厅目,這也會導(dǎo)致線上版本落后于master
分支番枚。
上面這種情況,只有master
一個主分支就不夠用了损敷。通常葫笼,你不得不在master
分支以外,另外新建一個production
分支跟蹤線上版本拗馒。
四路星、Gitlab flow
Gitlab flow 是 Git flow 與 Github flow 的綜合。它吸取了兩者的優(yōu)點瘟忱,既有適應(yīng)不同開發(fā)環(huán)境的彈性奥额,又有單一主分支的簡單和便利苫幢。它是 Gitlab.com 推薦的做法访诱。
4.1 上游優(yōu)先
Gitlab flow 的最大原則叫做"上游優(yōu)先"(upsteam first)垫挨,即只存在一個主分支master,它是所有其他分支的"上游"触菜。只有上游分支采納的代碼變化九榔,才能應(yīng)用到其他分支。
Chromium項目就是一個例子涡相,它明確規(guī)定哲泊,上游分支依次為:
- Linus Torvalds的分支
- 子系統(tǒng)(比如netdev)的分支
- 設(shè)備廠商(比如三星)的分支
4.2 持續(xù)發(fā)布
Gitlab flow 分成兩種情況,適應(yīng)不同的開發(fā)流程催蝗。
對于"持續(xù)發(fā)布"的項目切威,它建議在master
分支以外,再建立不同的環(huán)境分支丙号。比如先朦,"開發(fā)環(huán)境"的分支是master
,"預(yù)發(fā)環(huán)境"的分支是pre-production
犬缨,"生產(chǎn)環(huán)境"的分支是production
喳魏。
開發(fā)分支是預(yù)發(fā)分支的"上游",預(yù)發(fā)分支又是生產(chǎn)分支的"上游"怀薛。代碼的變化刺彩,必須由"上游"向"下游"發(fā)展。比如枝恋,生產(chǎn)環(huán)境出現(xiàn)了bug创倔,這時就要新建一個功能分支,先把它合并到master
焚碌,確認(rèn)沒有問題畦攘,再cherry-pick
到pre-production
,這一步也沒有問題呐能,才進入production
念搬。
只有緊急情況,才允許跳過上游摆出,直接合并到下游分支朗徊。
4.3 版本發(fā)布
對于"版本發(fā)布"的項目,建議的做法是每一個穩(wěn)定版本偎漫,都要從master
分支拉出一個分支爷恳,比如2-3-stable
、2-4-stable
等等象踊。
以后温亲,只有修補bug棚壁,才允許將代碼合并到這些分支,并且此時要更新小版本號栈虚。
五袖外、一些小技巧
5.1 Pull Request
功能分支合并進master
分支,必須通過Pull Request(Gitlab里面叫做 Merge Request)魂务。
前面說過曼验,Pull Request本質(zhì)是一種對話機制,你可以在提交的時候粘姜,@
相關(guān)人員或團隊鬓照,引起他們的注意。
5.2 Protected branch
master
分支應(yīng)該受到保護孤紧,不是每個人都可以修改這個分支豺裆,以及擁有審批 Pull Request 的權(quán)力。
Github 和 Gitlab 都提供"保護分支"(Protected branch)這個功能号显。
5.3 Issue
Issue 用于 Bug追蹤和需求管理臭猜。建議先新建 Issue,再新建對應(yīng)的功能分支咙轩。功能分支總是為了解決一個或多個 Issue获讳。
功能分支的名稱,可以與issue的名字保持一致活喊,并且以issue的編號起首丐膝,比如"15-require-a-password-to-change-it"。
開發(fā)完成后钾菊,在提交說明里面帅矗,可以寫上"fixes #14"或者"closes #67"。Github規(guī)定煞烫,只要commit message里面有下面這些動詞 + 編號浑此,就會關(guān)閉對應(yīng)的issue。
- close
- closes
- closed
- fix
- fixes
- fixed
- resolve
- resolves
- resolved
這種方式還可以一次關(guān)閉多個issue滞详,或者關(guān)閉其他代碼庫的issue凛俱,格式是username/repository#issue_number
。
Pull Request被接受以后料饥,issue關(guān)閉宵蛀,原始分支就應(yīng)該刪除现喳。如果以后該issue重新打開,新分支可以復(fù)用原來的名字渔伯。
5.4 Merge節(jié)點
Git有兩種合并:一種是"直進式合并"(fast forward)脓豪,不生成單獨的合并節(jié)點;另一種是"非直進式合并"(none fast-forword),會生成單獨節(jié)點。
前者不利于保持commit信息的清晰擂送,也不利于以后的回滾,建議總是采用后者(即使用--no-ff
參數(shù))唯欣。只要發(fā)生合并嘹吨,就要有一個單獨的合并節(jié)點。
5.5 Squash 多個commit
為了便于他人閱讀你的提交黍聂,也便于cherry-pick
或撤銷代碼變化躺苦,在發(fā)起Pull Request之前身腻,應(yīng)該把多個commit合并成一個产还。(前提是,該分支只有你一個人開發(fā)嘀趟,且沒有跟master
合并過脐区。)
這可以采用rebase
命令附帶的squash
操作,具體方法請參考我寫的《Git 使用規(guī)范流程》她按。