我記得本科時(shí)寫(xiě)論文,當(dāng)時(shí)不會(huì)版本管理工具北戏,每天都是按時(shí)間后綴備份個(gè)新文件夾负芋;某同學(xué)提醒我用 Git,我還不屑一顧——無(wú)知又自負(fù)嗜愈。最近旧蛾,我和一些非軟件相關(guān)行業(yè)的朋友聊天,他們竟然也是用 Git 做版本控制的蠕嫁,還用得很溜锨天。想來(lái),高效的生產(chǎn)工具在任何行業(yè)都是共通的剃毒。今天就借機(jī)聊聊我們?cè)谏a(chǎn)中常用到的幾種 Git 工作流程绍绘。
入門(mén)版
入門(mén)版 Git 模型只有一個(gè)默認(rèn)的 master 分支,操作基本無(wú)外乎 pull 和 push迟赃。
這種工作流很簡(jiǎn)單陪拘,我自己寫(xiě)博客就是一個(gè)入門(mén)版 master 分支:每天寫(xiě)一點(diǎn),順道加個(gè) commit 標(biāo)記一下纤壁,基本就沒(méi)啥他用了左刽。學(xué)生時(shí)代,我還見(jiàn)過(guò)某對(duì)小情侶 PK A 題酌媒,他們也是這種 Git 模式欠痴,回想起來(lái)還是挺有趣的。不過(guò)工程生產(chǎn)中秒咨,應(yīng)該不會(huì)有團(tuán)隊(duì)使用這種工作流喇辽;缺點(diǎn)顯而易見(jiàn):沖突和回滾的代價(jià)太大了。
普通版
組成開(kāi)發(fā)團(tuán)隊(duì)后雨席,我們得確保不會(huì)直接操作主分支了菩咨。最樸素的工作流就是:
- 開(kāi)發(fā)新功能前,每個(gè)人從 master 分支切出一條專(zhuān)屬的 feature 分支
- 功能實(shí)現(xiàn)后陡厘,將 feature 分支合并到 master 分支
- 假如出現(xiàn)沖突抽米,在自己的分支里解決沖突,再?lài)L試合并
這種工作流算是正式開(kāi)啟了團(tuán)隊(duì)成員的“并發(fā)”工作糙置。每個(gè)人只需關(guān)注自己的分支云茸,即便有沖突也是在自己熟悉的分支代碼上修改。
主分支功能單一谤饭,只需注意 MR(Merge Request)标捺,這使得集成一些自動(dòng)化操作變得簡(jiǎn)單可行了懊纳。新功能合并到 master 分支,會(huì)立即觸發(fā)生產(chǎn)環(huán)境的部署亡容;這確實(shí)挺方便的嗤疯,但是副作用也很明顯:生產(chǎn)環(huán)境變得不穩(wěn)定——新功能只在本地開(kāi)發(fā)環(huán)境證明可行,線(xiàn)上就不見(jiàn)得了萍倡。那該如何改進(jìn)呢身弊?
專(zhuān)業(yè)版
我們需要一個(gè)中間態(tài)辟汰,一個(gè)既能快速合并新功能列敲,又能證明線(xiàn)上運(yùn)行可行的分支——develop 分支。
develop 反映的是最新的代碼實(shí)現(xiàn)效果:
- develop 是從上一迭代的 master 切出的分支
- feature 則由 develop 分支切分出來(lái)帖汞;新功能實(shí)現(xiàn)后戴而,第一時(shí)間就合并到 develop 上
- 遇到 bug 也是先修復(fù) develop 代碼
- 通常 develop 分支也能觸發(fā)自動(dòng)化部署——staging 環(huán)境——幫助開(kāi)發(fā)或測(cè)試人員第一時(shí)間看到線(xiàn)上部署的效果
master 則是相對(duì)穩(wěn)定的分支:
- master 分支只由充分測(cè)試后的 develop 分支合并而來(lái)
- master 代碼可以直接部署到生成環(huán)境,或是交由 shipment 團(tuán)隊(duì)發(fā)布到商業(yè)環(huán)境中
- master 分支每次更新后翩蘸,通常會(huì)打個(gè) tag所意,用于標(biāo)記版本號(hào)
我自己所屬的團(tuán)隊(duì)曾長(zhǎng)期使用這種 Git 工作流。在一個(gè)開(kāi)發(fā)迭代里催首,如果有很明確的開(kāi)發(fā)階段和測(cè)試階段扶踊,這種工作流還是很實(shí)用的。只不過(guò)郎任,有時(shí)候測(cè)試方速度較慢秧耗,甚至能拖到下一個(gè)迭代中,這時(shí)的 develop 分支就比較尷尬了——既要處理新周期 feature舶治,又要修復(fù)上一迭代的 bug分井,顯然力不從心了。
旗艦版
如何解決上述煩惱霉猛?再加一個(gè)中間態(tài)唄——release 分支尺锚。
Release 分支
當(dāng)某一迭代的新功能開(kāi)發(fā)完畢后,我們會(huì)從 develop 分支切出一個(gè) release 分支:
- Release 分支一般用作 bugfix惜浅,絕大多數(shù)的人工測(cè)試——包括 Scenario 測(cè)試瘫辩、回歸測(cè)試、UI 測(cè)試等等——都會(huì)基于這個(gè)分支的代碼進(jìn)行坛悉;此外杭朱,Release 也可能合并一些文檔,或是非功能相關(guān)的業(yè)務(wù)代碼吹散,但是切記加入與該發(fā)布版本不相關(guān)的信息弧械。
- 而 develop 分支基本只服務(wù)于開(kāi)發(fā)人員;release 測(cè)試階段空民,develop 也可以同步進(jìn)行下一迭代的功能開(kāi)發(fā)刃唐。
Release 代碼被充分測(cè)試后羞迷,就可以合并到 master 分支,并打上版本 tag画饥;與此同時(shí)衔瓮,Release 也需要立馬合并回 develop 分支,使 develop 分支保持最新代碼抖甘。
Hotfix 分支
這里還存在一個(gè)問(wèn)題热鞍,假如 master 分支的代碼又發(fā)現(xiàn)了新的 bug,該如何處理衔彻?
Master 指向的是生產(chǎn)環(huán)境薇宠,修復(fù)生產(chǎn)環(huán)境的 bug 就是所謂的打補(bǔ)丁(patch)了艰额。我們通常會(huì)從 master 的特定 tag 上切出一個(gè)叫 hotfix 的分支澄港;bug 修復(fù)后,再合并回 master柄沮。使用 hotfix 分支的好處就是“快”——迅速修復(fù)回梧、迅速發(fā)布,避開(kāi)了 develop -> release -> master
的冗長(zhǎng)步驟祖搓。
打完補(bǔ)丁后狱意,我們也應(yīng)盡快將 hotfix 代碼 cherry-pick 到最近的 release 分支或是 develop 分支,使分支保持最新代碼拯欧。
這種 Git 工作流最早是在十年前详囤,由一個(gè)叫Vincent Driessen的作者發(fā)布于自己的博客上,之后被迅速借鑒到各大公司的軟件工程上哈扮。后來(lái)纬纪,他還自己開(kāi)發(fā)了一個(gè) git 擴(kuò)展工具——gitflow,指導(dǎo)開(kāi)發(fā)人員使用這套開(kāi)發(fā)流程管理代碼滑肉。
但是遇到更復(fù)雜的業(yè)務(wù)場(chǎng)景包各,我們又該怎么繼續(xù)擴(kuò)展 git 工作流呢?很簡(jiǎn)單靶庙,無(wú)限地添加不同命名的分支问畅。
沒(méi)有一個(gè)問(wèn)題是一個(gè)中間態(tài)不能解決的,如果有就再加一個(gè)中間態(tài)六荒!
我就聽(tīng)說(shuō)過(guò)類(lèi)似的事护姆,某廠(chǎng)要長(zhǎng)期同時(shí)開(kāi)發(fā)三個(gè)迭代周期的分支。要知道每個(gè)迭代光開(kāi)發(fā)就是數(shù)個(gè)月掏击;每個(gè)分支又會(huì)處在不同階段的測(cè)試周期中卵皂,什么時(shí)候結(jié)束還不知道;每個(gè)分支各自的依賴(lài)本身還在升級(jí)砚亭;還會(huì)接受客戶(hù)的要求灯变,在不同版本的分支里添加新需求殴玛。大家可以思考一下該怎么管理分支。
小結(jié)
OK添祸,這期介紹了四種開(kāi)發(fā)中常用到的 git 工作流滚粟,建議大家按照實(shí)際需求選取一種模式。也沒(méi)必要一上來(lái)就搞“旗艦版”刃泌,上述四種模式我都體驗(yàn)過(guò)凡壤,也是隨著項(xiàng)目變更逐步升級(jí)到進(jìn)階版的。很多時(shí)候耙替,我們的工程并沒(méi)有那么復(fù)雜亚侠,完全可以在其他方面動(dòng)腦經(jīng)解決問(wèn)題,而不是無(wú)限地增加分支林艘。Git 只是一款工具盖奈,不是解決問(wèn)題的關(guān)鍵混坞,人才是狐援!