分支策略概述#
分支策略是持續交付的基石。選擇正確的分支策略,可以讓團隊的協作更加順暢,減少整合衝突,提高交付效率。
沒有「最好」的分支策略,只有「最適合」的分支策略。選擇時需要考慮團隊規模、發布頻率、產品特性等因素。
主流分支策略比較#
主幹開發(Trunk-Based Development)#
主幹開發是最簡單也是最激進的分支策略:所有開發人員直接在主幹(main/master)上工作,或使用非常短命的特性分支(存活時間不超過一天)。
核心原則:
- 保持主幹隨時可發布
- 頻繁整合,每天至少一次
- 使用特性開關(Feature Toggle)控制未完成功能
適用場景:
- 持續部署的團隊
- 有完善自動化測試的項目
- 團隊成員經驗豐富,程式碼品質穩定
main ─────●─────●─────●─────●─────●─────→
↑ ↑ ↑ ↑ ↑
│ │ │ │ │
直接提交或短命分支(< 1 天)主幹開發對團隊能力和基礎設施要求較高。如果自動化測試不完善,直接在主幹上工作可能導致頻繁的建構失敗。
Git Flow#
Git Flow 是一種功能完備的分支模型,由 Vincent Driessen 在 2010 年提出,適合有計劃發布週期的項目。
分支類型:
| 分支 | 用途 | 生命週期 |
|---|---|---|
| main | 生產環境程式碼 | 永久 |
| develop | 開發主線 | 永久 |
| feature/* | 新功能開發 | 臨時 |
| release/* | 版本發布準備 | 臨時 |
| hotfix/* | 緊急修復 | 臨時 |
工作流程:
main ─────────────●───────────●─────────→
↑ ↑
│ │
release ─────────────●───────────●
↑ ↑
│ │
develop ────●────●───●────●──────●────●────→
↑ ↑ ↑ ↑
│ │ │ │
feature/A ───● │ │ │
│ │ │
feature/B ────────●────────● │
│
feature/C ────────────────────────●優點:
- 結構清晰,職責分明
- 支援並行開發多個版本
- 適合有固定發布週期的項目
缺點:
- 流程複雜,學習成本高
- 分支切換頻繁,容易出錯
- 不適合持續部署
GitHub Flow#
GitHub Flow 是 GitHub 推薦的簡化工作流,核心理念是「主幹即生產」。
工作流程:
- 從 main 建立特性分支
- 在特性分支上開發和提交
- 建立 Pull Request
- 程式碼審查和討論
- 部署到預覽環境測試
- 合併到 main 並部署到生產
main ─────────────●───────────●─────────→
↑ ↑
│ │
feature/A ─────────────● │
│
feature/B ─────────────────────────●GitHub Flow 的關鍵是:main 分支上的任何程式碼都是可部署的。這要求有完善的自動化測試和 CI/CD 流水線。
GitLab Flow#
GitLab Flow 是 GitHub Flow 的延伸,增加了環境分支的概念,更適合需要多環境部署的場景。
分支類型:
main → 開發主線
pre-prod → 預生產環境
production → 生產環境工作流程:
production ─────────────────────●─────────●─────→
↑ ↑
│ │
pre-prod ─────────────●───────●─────────●─────→
↑ ↑ ↑
│ │ │
main ────●────●───●───●───●────●────●─────→
↑ ↑ ↑ ↑ ↑
│ │ │ │ │
特性分支開發分支策略選擇指南#
| 因素 | 主幹開發 | Git Flow | GitHub Flow | GitLab Flow |
|---|---|---|---|---|
| 團隊規模 | 小型 | 中大型 | 小中型 | 中大型 |
| 發布頻率 | 持續 | 固定週期 | 高頻 | 高頻 |
| 複雜度 | 低 | 高 | 低 | 中 |
| 適合場景 | 持續部署 | 版本軟體 | Web 應用 | 多環境部署 |
特性開關(Feature Toggle)
特性開關是主幹開發的關鍵技術,允許在程式碼中控制功能的啟用和停用。
常見類型:
| 類型 | 用途 | 生命週期 |
|---|---|---|
| 發布開關 | 控制未完成功能 | 短期 |
| 實驗開關 | A/B 測試 | 中期 |
| 維運開關 | 緊急關閉功能 | 長期 |
| 權限開關 | 控制功能權限 | 永久 |
實作範例(偽程式碼):
if (featureToggle.isEnabled("new-checkout-flow")) {
return newCheckoutService.process(order);
} else {
return legacyCheckoutService.process(order);
}注意事項:
- 及時清理過期的開關
- 維護開關的文檔
- 測試開關的各種狀態組合
依賴管理#
良好的依賴管理是持續交付的重要組成部分,可以避免「在我電腦上能跑」的窘境。
Maven 依賴管理最佳實踐#
1. 使用依賴清單(BOM)
BOM(Bill of Materials)可以統一管理多個相關套件的版本:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.7.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>2. 父 POM 繼承
建立組織級的父 POM,統一管理:
- 公共依賴版本
- 外掛程式組態
- 建構設定
<parent>
<groupId>com.company</groupId>
<artifactId>company-parent</artifactId>
<version>1.0.0</version>
</parent>3. 依賴收斂
依賴衝突是 Java 專案的常見問題。當同一個套件被不同版本間接引入時,可能導致難以排查的執行期錯誤。
解決方法:
- 使用
mvn dependency:tree分析依賴樹 - 使用
<exclusions>排除衝突依賴 - 使用 Maven Enforcer 外掛程式強制依賴收斂
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<dependencyConvergence/>
</rules>
</configuration>
</execution>
</executions>
</plugin>私有倉庫管理#
組織應該建立私有 Maven 倉庫(如 Nexus、Artifactory),用於:
- 快取公共套件,加速建構
- 發布內部套件
- 控制外部依賴的准入
程式碼回滾#
程式碼回滾是持續交付的安全網,理解不同場景下的回滾策略至關重要。
回滾場景分類#
場景一:個人分支回滾
在個人開發分支上撤銷提交,可以使用 git reset:
# 撤銷最近一次提交,保留工作區變更
git reset --soft HEAD~1
# 撤銷最近一次提交,丟棄工作區變更
git reset --hard HEAD~1
# 強制推送到遠端(僅限個人分支)
git push -f origin feature/my-branch
git reset --hard和git push -f是危險操作,會重寫歷史。絕對不要在共享分支(如 main、develop)上使用。
場景二:整合分支回滾
在已經合併到主幹的程式碼上回滾,應該使用 git revert:
# 撤銷某次提交,建立一個新的反向提交
git revert <commit-hash>
# 撤銷一個合併提交
git revert -m 1 <merge-commit-hash>git revert 的優點:
- 不會重寫歷史
- 可以追溯回滾記錄
- 安全地用於共享分支
Reset vs Revert 比較#
| 特性 | git reset | git revert |
|---|---|---|
| 歷史記錄 | 重寫歷史 | 保留歷史 |
| 適用分支 | 個人分支 | 共享分支 |
| 協作影響 | 影響他人 | 不影響他人 |
| 操作結果 | 移除提交 | 新增反向提交 |
緊急回滾流程
當生產環境出現問題需要緊急回滾時:
第一步:確認問題
- 確定問題確實由最近的發布引起
- 評估影響範圍
第二步:執行回滾
# 方法一:部署回滾(推薦)
# 在 CI/CD 系統中重新部署上一個穩定版本
# 方法二:程式碼回滾
git revert <problematic-commit>
git push origin main
# 觸發 CI/CD 流水線第三步:事後分析
- 記錄問題原因
- 更新測試用例
- 改進發布流程
團隊分支實踐案例#
以下是一個「兩個披薩團隊」的週迭代分支管理實踐:
週一:迭代開始#
# 從 main 建立本週的特性分支
git checkout main
git pull origin main
git checkout -b feature/sprint-42-user-profile週二至週四:開發階段#
# 每天同步主幹變更
git fetch origin main
git rebase origin/main
# 頻繁提交小變更
git add .
git commit -m "feat: add avatar upload component"提交訊息應該遵循 Conventional Commits 規範:
feat:新功能fix:錯誤修復docs:文檔變更refactor:重構test:測試相關
週五:整合與發布#
# 最後一次同步主幹
git fetch origin main
git rebase origin/main
# 推送並建立 Pull Request
git push origin feature/sprint-42-user-profilePull Request 流程:
- 自動化測試通過
- 至少一位同事審查
- 解決審查意見
- 合併到 main
- 自動部署到測試環境
- 驗證後部署到生產
分支命名規範#
| 前綴 | 用途 | 範例 |
|---|---|---|
| feature/ | 新功能 | feature/user-auth |
| fix/ | 錯誤修復 | fix/login-timeout |
| hotfix/ | 緊急修復 | hotfix/security-patch |
| refactor/ | 重構 | refactor/api-layer |
| docs/ | 文檔 | docs/api-guide |
總結#
程式碼管理是持續交付的基礎設施,良好的分支策略和版本控制實踐可以顯著提升團隊效率。
關鍵要點:
- 根據團隊特點選擇合適的分支策略
- 保持主幹的健康狀態,確保隨時可發布
- 建立完善的依賴管理機制
- 理解不同場景下的回滾策略
- 遵循一致的提交和分支命名規範
工具和流程都是為人服務的。分支策略的最終目標是提升團隊協作效率,而不是增加流程負擔。如果現有策略造成太多摩擦,應該及時調整。