Trunk Based Development
Trunk Based Development(主幹開發,簡稱 TBD)是一種 Git 分支策略。它的核心精神是:所有開發者都圍繞著同一條主幹分支(trunk,通常就是 main)進行協作,並且頻繁地(至少每天一次)將自己的修改整合回主幹。
核心規則
- 只有一條長期存在的分支:
main(也就是 trunk)。 - 功能分支(feature branch)即使存在,也是短命的,生命週期通常以「小時」或「一兩天」為單位,完成後立刻合併回主幹並刪除。
- 主幹必須隨時保持在可發布的狀態,每一次合併進來的程式碼都要能通過建置與自動化測試。
- 不應該長期維護
develop、release、feature/*等多條平行的長壽分支。
main: A───B───C───D───E───F (隨時可發布)
\ \ /
\ └─ 短命分支(數小時內合併)
└──── 短命分支
與 Git Flow 的差異
很多團隊熟悉的是 Git Flow,它有 main、develop、feature/*、release/*、hotfix/* 等多條長壽分支。兩者的差別大致如下:
| 比較項目 | Git Flow | Trunk Based Development |
|---|---|---|
| 長壽分支數量 | 多(main、develop、release…) | 一條(main) |
| 分支存活時間 | 長,可能數週 | 短,數小時到一兩天 |
| 整合頻率 | 低,接近發布時才大量整合 | 高,每天多次 |
| 合併衝突 | 容易累積成大型衝突 | 小且頻繁,容易解決 |
| 適合的發布節奏 | 版本式、週期較長的發布 | 持續交付 / 持續部署 |
優點
- 減少合併衝突(merge hell):因為每個人都頻繁地把小批量的修改合進主幹,每次整合的差異都很小,衝突自然又小又好解。相對地,長壽分支拖越久,最後合併時的衝突就越痛苦。
- 更快得到回饋:程式碼很快進到主幹並跑過自動化測試,問題能在第一時間被發現,而不是累積到發布前才爆發。
- 降低整合風險:「持續整合(Continuous Integration)」這個詞的本意就是「持續地把大家的程式碼整合在一起」。TBD 才是真正落實 CI 精神的分支策略。
- 單一事實來源:所有人看的都是同一條
main,不會出現「到底哪條分支才是最新的?」這種困惑。 - 更容易做持續部署:主幹隨時可發布,搭配自動化流程就能做到一天部署多次。
為什麼在敏捷開發下會是比較好的選擇
敏捷開發強調小步快跑、快速迭代、儘早且持續地交付可用的軟體。Trunk Based Development 的特性正好支撐這些目標:
- 小批量交付:敏捷希望把工作切成小塊、頻繁交付。TBD 的短命分支與頻繁整合,天然鼓勵把工作拆小。
- 快速回饋迴圈:敏捷重視快速回饋。程式碼越快進到主幹、越快跑測試,就越快知道方向對不對。
- 擁抱變化:當每次整合的差異都很小,要調整方向、回退、重做的成本也低,符合敏捷「擁抱變化」的精神。
- 支撐 CI/CD:敏捷團隊通常搭配持續整合與持續交付,而 TBD 是讓 CI/CD 真正運作起來的前提——分支拖太久,CI 就名存實亡。
TBD 的好處來自於完善的 CI
Trunk Based Development 並不是「無條件地比較好」,它有前提。 它的優點是建立在以下配套之上的:
- 完善的自動化測試:因為主幹要隨時可發布,必須靠自動化測試把關,否則頻繁整合反而會頻繁地把 bug 帶進主幹。
- Feature Flag(功能旗標):當一個功能還沒做完、卻又要頻繁合進主幹時,常用 feature flag 把未完成的功能藏起來,先合併、但先不啟用。
- 小而頻繁的提交習慣與快速的 code review 文化:分支要能短命,review 就不能變成瓶頸。
換句話說,TBD 與其說是一條「規定」,不如說是一套「需要團隊紀律與自動化基礎設施支撐的實踐」。在缺乏自動化測試、團隊還不習慣小步提交的情況下貿然導入,可能會踩到「主幹常常壞掉」的坑。先把測試與 CI 補起來,再導入 TBD,會順利很多。
實務上的常見做法
- 直接在
main上做小修改,或開生命週期極短的分支,當天合併。 - 透過 Pull Request 搭配自動化測試與 code review 把關,但要追求快速 review、快速合併。
- 用 feature flag 隱藏尚未完成或尚未要上線的功能。
- 需要對外發布版本時,從
main拉出一條 release 分支(這條 release 分支本身也是短命的,只用來打 tag 與必要的修補),而不是長期維護它。