豬齒魚實踐之持續交付中的分支管理與版本控制
現在越來越多的項目使用Git作為版本控制的工具,通過Git進行分支和Tag管理,大多數情況這個過程都由手工完成,缺乏相應的規範,對於分支和版本號的控制也很隨意,出現這樣的情況往往是大家對軟體交付過程中的軟體版本控制不夠重視,「只要確保軟體是最新的版本即可」,甚至是項目管理的漏洞或者缺陷。其實軟體的版本控制以及分支管理貫穿於整個軟體產品的生命周期,日常的項目管理對於開發團隊能否有節奏且順利的交付軟體也很重要。
的確!頻繁的衝突搞的開發人員頭暈腦脹,例如,一次項目在程式碼合併時出現了衝突,導致整個項目組挨個排查,花費了大半天的時間,影響開發效率還浪費資源;開發人員隨意創建分支,各種不規範的合併使得Git Graph線條雜亂無章,完全看不出來主幹發展的脈絡;提交資訊混亂,不知道這次提交是因為什麼,實現了什麼功能 ,解決了什麼問題。
本文並不是一篇技術文章,其中也沒有讓別人耳目一新的觀點或者論述。本文是為我們這些希望進行簡單、有效地協作的人準備的。任何參與到軟體開發的人,無論承擔何種角色,都可能對其感興趣——畢竟每個人都會用到分支和合併。本文將結合Choerodon豬齒魚為大家闡述如何進行方便有效的分支管理和版本控制,以及如何選擇適合自身的版本控制模型。
如何來解決這些問題呢?
有經驗的老司機可能會說,「建立規範」。
是的,只有建立規範,才能抑制不好的事情繼續在項目組蔓延。至於建立什麼樣的規範?我們不妨先制定一個目標。
目標
- 簡單——所有的團隊成員每天都會使用這些模式,所以相關規則和程式必須要簡單明了。
- 靈活——可選擇不同的分支管理模型,例如GitFlow、GitLabFlow或者GitHubFlow,甚至自定義。
- 可視化——介面化比命令行更安全可控,將分支管理模型的規則和約定固化到系統中。
- 需求與程式碼關連——分支需要和具體的任務需求關連。
作為一個有經驗項目管理者,或者產品負責人,你一定會思考一個問題:我們項目組在開發過程中應如何管理分支?不錯,分支管理將和項目組開發人員日夜伴隨,如果採用了一個不合適的分支管理模型,那麼可以想像兄弟們得多麼的痛苦。
Okay,那麼就從分支管理模型開始……
分支管理規範
GitFlow、GitHubFlow等都是已經被證明很有效的分支管理模型,但是這些更多的是書面的規則、約定,基本上是靠著程式設計師的自覺性和Git命令一起維持著這個約定,其實無數的經驗告訴我們「這很脆弱」。所以,如何使用系統介面化操作將這些規則和約定表示出來,就變得很有意思。
分支管理模型
不要著急,先來看看 Choerodon 豬齒魚提供的分支模型,Choerodon使用 GitLab 進行分支管理,默認分支為 master。目前支援七種常見的分支類型:
- master:主分支,用於版本持續發布;
- develop:開發分支,即日常迭代使用的開發分支,用於日常開發持續集成;
- feature:特性分支,用於日常開發時切出分支進行單功能開發;
- bugfix:故障修補分支,通常用於修復故障;
- release:發布分支,適用於產品發布、產品迭代;
- hotfix:熱修分支,用於產品發布後修復缺陷;
- custom:自定義分支,用戶可以自定義需要的分支類型。
注:
- develop是GitFlow分支模型的重要組成部分。
- bugfix旨在與敏捷的問題類型(故障)呼應,用於標識此分支的任務是修復某個故障。
這7個分支就是我們手中的7個魔方,通過這7個魔方的組合可以變化出無盡的分支管理模型,比如GitHubFlow。
GitHubFlow分支模型只存在一個master主分支,日常開發都合併至master,永遠保持其為最新的程式碼。
- 在領到日常開發任務時,基於master創建feature特性開發分支,提交程式碼後,合併至master並刪除feature。
- 在領到修復故障的任務時,基於master創建bugfix故障修補分支,提交程式碼後,合併至master並刪除bugfix。
- 需要發布時,同樣需要基於master創建release,生成的應用版本部署在UAT測試環境進行測試,若需要修改則提交至release。
- 產品上線後發現故障需要緊急進行熱修復時,則基於tag創建hotfix,將修復的程式碼提交至hotfix;部署該分支上的版本通過驗收後,基於hotfix打出熱修版本的tag,如0.8.1。
- 由於新版本的迭代也同時進行,所以需要在hotfix上rebase master,變基至master分支最新的提交,再合併至master並刪除hotfix,就可以將本次修改的提交應用至master上。
這個分支模型的優勢在於簡潔易理解,將master作為核心的分支,程式碼更新持續集成至master上。根據目前收集到的反應來看,得到了更多的好評,認為GitHubFlow分支模型更加輕便快捷。
如果GitHubFlow不合適,可以使用GitLabFlow或者GitFlow,也可以自行定義規則。這裡沒有「銀彈」,只是相對比較靈活的配置。
分支命名規約
有了分支管理模型,還需要命名規約,不同類型的分支命名方式應該不同,值得慶幸的是,豬齒魚已經幫你完成了這個步驟。feature、bugfix分支的分支名使用的是關聯問題的issue號(在豬齒魚中打通了需求和程式碼分支的關連關係),對於release及hotfix,分支名可命名為需要發布的版本號,如0.8.0、0.8.1等。在這裡使用到了類似0.8.0這樣的版本編號規則,如果你對此不了解,沒有關係,在下面將詳細的介紹。
提交命名規約
除了分支的名稱需要規範,提交的命名也同樣如此。不幸,豬齒魚並沒有把這個規則固化到系統中,需要團隊共同遵守。
格式為:[操作類型]操作對象名稱,如[ADD]readme,代表增加了readme描述文件。
常見的操作類型有:
- [IMP] 提升改善正在開發或者已經實現的功能
- [FIX] 修正BUG
- [REF] 重構一個功能,對功能重寫
- [ADD] 添加實現新功能
- [REM] 刪除不需要的文件
合併請求
合併請求是開發過程中必不可少的一個環節,其中有如下一些重要的事情要做:
- 程式碼Review
- 啟動CI
- 單元測試
- 程式碼品質檢查
版本號規則
在軟體管理的領域裡存在著被稱作「依賴地獄」的死亡之谷,系統規模越大,加入的套件越多,你就越有可能在未來的某一天發現自己已深陷絕望之中。
—— Tom Preston-Werner 的《語義化版本2.0.0》
在這裡我們不去解讀到底什麼是「依賴地獄」,大家可以到語義化版本2.0.0中了解。那麼,我們的重點是什麼呢?在這之前,先了解一下「語義化的版本控制」
版本格式:主版本號.次版本號.修訂號,版本號遞增規則如下:
1.主版本號:當你做了不兼容的 API 修改,
2.次版本號:當你做了向下兼容的功能性新增,
3.修訂號:當你做了向下兼容的問題修正。
先行版本號及版本編譯資訊可以加到「主版本號.次版本號.修訂號」的後面,作為延伸。
這就是「語義化的版本控制」最核心的規則,當然這不是全部,Tom Preston-Werner還詳細的闡述了主版本號、次版本號和修訂號的變化遞增規則,不過這些規則很長,很複雜。
沒有關係,豬齒魚幫我們做了這些複雜的事情,將「語義化的版本控制」固化到了系統中,簡而言之,
- 當進行程式碼打包時,而非發布新版本
將版本號規則定為年.月.日-時分秒-分支名
。如:2018.7.20-152837-hotfix-0.8.1
,這個時間是當前提交時間。當程式碼提交到各個分支上時會自動觸發CI,生成版本號規則如上所示。
- 當需要發布新版本時,例如如
0.8.0
、0.8.1
- 主版本號:當做了不兼容的 API 修改或功能強大的升級,可以將主版本號的數值增加1。
- 次版本號:當做了向下兼容的功能性新增或是功能上的小迭代,可以將次版本號的數值增加1。
- 修訂號:當做了向下兼容的問題修正,但功能上沒有很大的變化,可以將修訂號的數值增加1。
需求與程式碼關連
一直以來,需求一般和系統的功能聯繫在一起,但是與程式碼關連卻不常見,如果能將需求和程式碼聯繫在一起,奇妙的化學反應就發生了。
「我們可以追溯到一個用戶故事對應了哪些分支,哪幾個提交」, 「甚至出現了一些BUG,可以找到是哪個分支提交的,當初為了發布XXX新的需求」, 「不僅如此,我們通過需求與程式碼分支關連,能夠查看到哪些需求已經部署到了測試環境,那些需求已經部署到了正式環境」, 「可以做從業務到程式碼的整個鏈條的統計分析…」
…
這一切,豬齒魚已經幫助項目管理者和程式設計師實現了。在豬齒魚的敏捷管理服務中,可以通過用戶故事、任務、缺陷等直接一鍵創建分支,然後,你可以從git checkout -b 開始愉快而又有挑戰的一天。不僅如此,也可以在分支管理中,將現有的分支關連到用戶故事、任務或者缺陷。
總結
回顧一下我們的目標,簡單、靈活、可視化,以及需求與程式碼關連。版本控制一直都是一件說起來容易,做起來難的事情,但是我們做到了,重要的是豬齒魚將這些特點和規則固化到了DevOps流程中,讓我們忘記複雜易錯的操作,把精力放到業務開發上。希望我們的分享能夠給大家帶來幫助。
本文由豬齒魚技術團隊原創,轉載請註明出處