主幹開發強調,開發者應該要頻繁把完成的程式提交到主幹。
以下介紹兩種常見做法:
以 Git 為例,直接提交是在本機主幹上修改程式,完成審查與驗證後,將提交推送到遠端主幹;短期分支則是從主幹建立分支,在分支上修改程式,透過 PR 完成審查與驗證後,再合併回主幹。
在 Git 裡,本機提交是把變更記錄在自己的版本庫,推送則是把提交傳到遠端分支。推送到功能分支之後,仍須合併到主幹,提交才會進入團隊共同使用的主幹版本。
以下沿用 Kevin 調整前端共用模組的假想情境,先說明這兩種流程的具體步驟,最後比較各自的優缺點與適用條件。
Kevin 負責調整前端共用模組,Elvina 的程式需要使用他調整後的模組,因此希望能從主幹取得。Phoebe 則協助 Kevin 做程式碼審查。
先假設 Kevin 已經整理出 Elvina 需要的那部分模組調整,不必等待其他尚未完成的程式,就能先整合到主幹。他已和 Elvina 等使用這個模組的成員確認要改變與保留的行為,也確認這部分可以先進行驗證。
以下流程會以 main 作為主幹。Kevin 會在本機完成必要的建置與驗證,並請 Phoebe 審查。程式進入主幹後,他還要確認主幹的驗證結果,讓 Elvina 能取得已通過驗證的版本。
如果採用直接提交到主幹的方法,版本庫必須要允許 Kevin 直接推送到 main。
直接提交時,Kevin 具體要做的事是:在本機主幹上修改、驗證並留下提交,再推送到團隊共用的主幹。
Kevin 先查看主幹的驗證結果,確認通過後,將主幹更新整合到本機。接著修改共用模組,並加入測試,用來確認修改後的行為符合需求,以及原本使用這個模組的程式仍能正常運作。
程式準備好後,Phoebe 與 Kevin 一起檢視差異,Kevin 再依審查結果調整程式與測試。兩人也可以採用配對開發,在撰寫時持續檢視。完成修改與審查後,Kevin 在本機執行與伺服器端相同的完整建置,確認通過後,再留下提交與修改理由。
透過共同檢視或配對開發,即使沒有 PR,也能在推送前完成程式碼審查。
準備推送時,Kevin 要先確認主幹是否有新的提交。如果有,就先取得更新、完成整合並重新驗證,再推送到遠端的 main。
推送後,其他人就能取得這次提交,但伺服器端的驗證可能還沒完成。即使推送前已在本機通過驗證,Kevin 仍要查看主幹的建置結果,確認整合後的版本是否通過驗證。
若主幹的驗證尚未完成,Kevin 就要等待結果。若驗證失敗,他與相關成員就要通知團隊,修復問題或還原變更,再重新驗證。
下圖呈現直接提交到主幹時,審查與驗證通過的流程,時間由上往下:

採用短期功能分支時,Kevin 具體要做的事是:從主幹建立分支,在分支上修改、驗證並留下提交,再推送分支並提出 PR。完成審查與驗證後,將程式合併回主幹,再刪除分支。
從建立到合併與刪除,建議控制在一、兩天內;這段時間也包含撰寫程式、等待審查與執行驗證。
雖然稱為「功能分支」,也可以用來修正錯誤或重構。同一項需求可以分成幾個步驟,分別透過短期功能分支完成,讓每一步的程式都能先合併回主幹,不必等待整項需求完成。一個 PR 可以包含多個提交,但這次準備合併的程式必須能與主幹一起運作,並完成必要驗證。
短期功能分支要縮短的是程式等待整合的時間,而不只是分支存在的時間。如果只是把尚未合併的程式移到另一條新分支,其他人仍然無法從主幹取得這些程式,那依然沒有達到主幹開發所想達到的目的。
如果 Kevin 採用短期功能分支,他會先查看主幹的驗證結果。確認通過後,取得主幹的最新版本,並從這個版本建立分支。
接著在分支上修改共用模組並加入測試,在本機執行建置,確認驗證通過後,再留下提交與修改理由。然後將分支推送到遠端,發出 PR,請 Phoebe 審查這次準備合併到主幹的程式。
Kevin 會在 PR 中說明修改目的、影響範圍,以及已完成的驗證,讓 Phoebe 能理解這次調整並提出意見。
如果 Phoebe 提出需要調整的地方,Kevin 就修改程式與測試,再請她確認調整結果。
準備合併前,Kevin 要執行建置,驗證分支與主幹合在一起的結果。審查與必要驗證都通過後,再合併 PR。
合併後,也要查看主幹的驗證結果。若驗證尚未完成,就等待結果;若驗證失敗,就通知團隊,修復問題或還原變更,再重新驗證。
確認主幹驗證通過後,Kevin 就可以刪除這條短期功能分支,保留合併後的提交歷史與 PR 討論。後續開發再從更新後的主幹建立新分支。
此時 Elvina 就能從主幹取得所需模組,接著驗證它與自己程式的組合。
下圖呈現短期功能分支的流程,同樣以審查與驗證通過為例,時間由上往下:

兩種流程都可能遇到同一件事:Kevin 已經完成驗證,但在他準備推送或合併之前,Phoebe 又把另一項調整整合進主幹。
Kevin 原本驗證的是自己的程式與當時主幹版本的組合,還沒有確認加入 Phoebe 的調整後是否仍能正常運作,因此需要整合主幹更新,再重新驗證。
下圖用 A 與 B 表示主幹更新前後的版本,時間由上往下:

即使工具沒有報出文字衝突,Phoebe 的提交仍可能改變 Kevin 依賴的行為。重新驗證要確認的是這些程式是否能一起運作;影響先前審查判斷的部分,也要重新確認。
使用 PR 時,也要確認通過的驗證對應哪個版本。如果驗證的是版本 A 加上 Kevin 的程式,但主幹已經更新成 B,就需要重新驗證版本 B 加上 Kevin 的程式,不能只看 PR 上顯示通過。
Kevin 重新驗證時,其他人仍可能把新的提交整合進主幹。因此,團隊需要協調推送或合併的順序,避免 Kevin 驗證通過後,主幹又有了尚未一起驗證的新提交。
與直接提交的流程相比,PR 提供了集中保留討論、核准與檢查結果的位置,Kevin 與 Phoebe 也可以在不同時間回應。
以下是前面兩條流程的差異比較:
| 考量 | 直接提交 | 短期分支 |
|---|---|---|
| 審查安排 | 推送前一起檢視程式,需要安排雙方都有空的時間 | 透過 PR 非同步審查,需要安排審查者及時檢視與回覆 |
| 權限 | 需要允許推送到主幹 | 可以透過合併權限與核准規則管理 |
| 驗證 | 推送前驗證與主幹整合後的版本,推送後確認共同結果 | 合併前驗證分支與主幹合在一起的結果,合併後確認共同結果 |
| 可能的等待 | 等待共同審查、執行建置,以及其他人先推送後的重新驗證 | PR 排隊、往返修改與建置 |
如果團隊能安排成員一起檢視程式,可以採用直接提交;如果需要讓審查者在不同時間檢視與回覆,可以透過短期功能分支與 PR 進行。兩種做法都需要及時取得驗證結果,並安排成員在主幹驗證失敗時處理問題。
團隊人數也是另一個考量。如果多人同時提出審查,需要有人分配或認領,避免 PR 一直沒有人看。若多人同時準備把程式整合進主幹,也需要確認誰先推送或合併,後完成的人再取得更新並重新驗證。選擇流程時,要看團隊如何處理這些等待與更新,不能只用人數決定。
無論是直接提交到主幹,還是使用短期功能分支,都要先取得主幹更新,完成修改、審查與驗證,並在程式進入主幹後確認驗證結果。團隊可以依審查時間、建置速度與版本庫權限選擇做法;主幹驗證失敗時,也都需要有人修復問題或還原變更。
即使修改已經很小,等待審查仍可能讓它一直留在分支,因此也需要讓必要的討論與審查提早進行。