🎯 什麼情境該想到我
當你「開發者各自窩在長命的 feature branch 裡,合併回主幹時變成 merge hell」的時候。
⚙️ 怎麼用(步驟 / 公式)
意圖:把批量大小縮到最小,讓合併問題在還很小的時候就被發現與修正,逼近單件流(single-piece flow)的理想。
核心規則:實施持續整合與主幹開發,所有開發者每天至少把程式碼 check in 進 trunk 一次。這麼頻繁地簽入,把批量大小縮小到「整個開發團隊一天的工作量」;簽入越頻繁,批量越小,越接近單件流理想。
理由:
- 頻繁提交 trunk 意味著可以對整個軟體系統跑所有自動化測試,並在某個變更弄壞其他部分或干擾到別的開發者時收到警報。合併問題還小的時候被偵測到,就能更快修正。
- 每日簽入的紀律也逼我們把工作拆成更小的塊,同時保持 trunk 處於可運作、可發布的狀態;版控因此成為團隊溝通的核心機制。
分支策略光譜(Jeff Atwood,Stack Overflow 創辦人、Coding Horror 作者)
- Optimize for individual productivity(為個人生產力最佳化):每個人都在自己的私有分支工作,彼此獨立、沒人能干擾別人的工作;但合併變成惡夢,協作幾乎滑稽地困難——要看到完整系統的最小一部分,都得把每個人的工作痛苦地跟其他所有人合併。
- Optimize for team productivity(為團隊生產力最佳化):所有人在同一個共同區域工作,沒有分支,只有一條長而不間斷的直線開發。沒什麼要理解的,提交很簡單;但每次提交都可能弄壞整個專案、讓所有進度戛然而止。
書中明說:合併分支所需的努力隨分支數量指數成長;而解決技術債問題(Ward Cunningham 所述)正是創立持續整合與主幹開發實踐的首要原因之一——就是要為團隊生產力而非個人生產力做最佳化。
閘門提交(gated commits)
- 可以設定部署管線拒絕任何會讓我們離開可部署狀態的提交(程式碼或環境變更皆然)。
- 做法:部署管線先確認提交的變更能成功合併、如預期建置、並通過所有自動化測試,之後才真正合併進 trunk;若不通過就通知開發者,讓他在不影響價值流中其他人的情況下修正。
Bazaarvoice 案例(2012,Ernest Mueller)
- 系統規模:主力的 Bazaarvoice Conversations 是近五百萬行 Java 的單體應用(可回溯到 2006 年)、跨一萬五千個檔案,服務跑在四個資料中心與多家雲端供應商的一千兩百台伺服器上;當時公司營收 1.2 億美元、正在準備 IPO。
- 首次嘗試兩週發布(2012 年 1 月):「It didn’t go well.」造成巨大混亂,客戶提報了四十四件生產事故,管理層的反應是「以後別再這樣做了」。
- Mueller 找出三個核心問題:缺乏測試自動化、版控分支策略允許開發者一路 check in 到發布當下、微服務團隊的獨立發布常與單體發布互相干擾。
- 對策:接下來六週開發者停掉功能開發,專心寫自動化測試套件(JUnit 單元測試、Selenium 回歸測試),並在 TeamCity 上跑起部署管線。
- 結果:1 月 44 件客戶事故 → 3/6 發布遲五天、5 件事故 → 3/22 準時、1 件事故 → 4/5 準時、0 件事故。
連帶效果:有了這些實踐,就能再次修改 done 的定義(見修改完成的定義第二版:created from trunk using a one-click process, and validated with automated tests),並消除「專案結尾另設獨立測試與穩定化階段」的做法。
原文:「Our countermeasure to large batch size merges is to institute continuous integration and trunk-based development practices, where all developers check in their code to trunk at least once per day.」(L5880–5882)
原文:「Solving this problem was one of the primary reasons behind the creation of continuous integration and trunk-based development practices, to optimize for team productivity over individual productivity.」(L5871–5874)
原文(Bazaarvoice):「It didn’t go well. It caused massive chaos, with forty-four production incidents filed by our customers.」(L5943–5944)
🧪 我實際套用的紀錄
- (待填)
⚠️ 注意 / 什麼時候不適用
- 每天簽入 trunk 的前提是有可信的自動化測試與紅燈立即處置,否則就是 Atwood 說的「每次提交都可能弄壞整個專案」。
- Bazaarvoice 的解法不是純粹的 trunk:他們改成 trunk/branch 發布模型,每兩週開一條專用 release branch,非緊急不得再提交,變更要走簽核流程再經 QA 推上生產——照抄前先看清楚脈絡。
- 合併困難時人會不敢重構,而依賴最多的程式碼往往是重構報酬最高的地方;主幹開發同時是技術債的預防手段。