05-分支策略与协作模型
Git 本身只是工具,分支策略才是团队协作的契约。没有策略,再好的工具也会沦为"主分支直接 push、commit message 全是 fix、合并冲突靠谁先来谁赢"的混乱。本章对比四种主流分支模型,给出选型维度。
GitFlow#
Vincent Driessen 2010 年提出,最重、分支最多的模型。核心包含五种分支:
main:永远是生产代码develop:集成分支,下一个版本的开发基准feature/*:功能开发,从 develop 切,合回 developrelease/*:发版准备,从 develop 切,测试完合回 main 和 develophotfix/*:紧急修复,从 main 切,合回 main 和 develop
main: ──────────●──────────────────────────●────
↑ ↑
release: └──●──────────●────────────┘
↑ ↓
develop: ──●──────────●──────────────────────●────
↑ ↑ ↓ ↑
feature: └─────────●──────┘ └──feature-B────┘适合场景:有明确版本号的软件(手机 App、桌面客户端)、需要同时维护多个版本、QA 测试周期长的团队。
缺点:维护成本高,长生命 feature 分支容易积累大量冲突;对 CI/CD 成熟的团队显得过度设计。Driessen 自己在 2020 年的一篇博客里也说,GitFlow 适合"有版本号的发布软件",而 Web 服务应该用更轻的 GitHub Flow。
GitHub Flow#
GitHub 2011 年左右推广的简化版:只有 main 是长期分支,其他都是短命 feature 分支。
git checkout -b feature/user-auth main
# 开发、提交
git push origin feature/user-auth
# 发起 PR,Code Review
# Review 通过后 merge 进 main
# CI/CD 自动部署main: ──●──●──●──●──●──●──●──●──
\ /
●──●──●──● feature/login(短命)适合场景:持续部署的 Web 服务、小型团队(5-15 人)、发版频率高(每天多次)。
缺点:对 CI/CD 和测试覆盖率要求高;main 分支质量完全依赖 PR Review 质量;没有内置的"release 准备"阶段。
GitHub Flow 的隐含假设是 main 永远可部署。这意味着:
- 每个 PR 合并前必须通过完整 CI(lint + test + build)
- 测试覆盖率要够高,否则 main 质量不可信
- 部署是自动化的,不需要"发版窗口"
如果团队还没达到这个水平,不要硬上 GitHub Flow——main 会频繁出问题,最后被迫回退到 GitFlow 模式。
GitLab Flow#
GitLab Flow 是 GitFlow 和 GitHub Flow 的折中——主分支 + 环境分支:
main (开发主干)
└── pre-production (预发布环境)
└── production (生产环境)代码从 main → pre-production → production 级联推进,每个环境对应一个分支。发版就是"把 main 合到 pre-production,验过再合到 production"。
适合场景:有多个部署环境(dev/staging/prod)且需要环境隔离的团队,不想用 GitFlow 的全套 release 分支但又想要"发版准备"环节。
缺点:环境分支可能积累差异,长期会出现"main 和 production 越来越不像",回合并冲突大。缓解办法是频繁从 production 往 main 做反向合并,保持环境分支和主干不要偏离太远。
环境分支 vs GitOps 声明#
现代 GitOps 实践里,"环境分支"的概念正在被"同一分支 + 不同 overlay"取代:
# 传统 GitLab Flow:环境 = 分支
main → pre-production → production
# GitOps 模式:环境 = overlay 目录
main(代码)
└── gitops 仓库
├── overlays/qa/ → newTag: abc123
├── overlays/pre/ → newTag: abc123
└── overlays/prod/ → newTag: abc123(推进时改)GitOps 模式的好处是"同一个镜像 tag 贯穿所有环境",不需要环境分支——推进部署就是改 overlay 里的 newTag。
Trunk-Based Development(TBD)#
所有人直接在 main(trunk)上工作,或使用极短命的分支(存活不超过一两天)。大特性用 Feature Flag 控制上线时机,而不是靠分支隔离。
git checkout -b feat/small-change
# 最多 1 天内完成
git push origin feat/small-change
# 快速 Review,当天合入 mainmain: ─●─●─●─●─●─●─●─●─●─●─●─●─●─
\ \ /\ /
● ●────● ●────● (极短命分支,< 1 天)Feature Flag 是 TBD 的关键基础设施。没做完的功能用 flag 关掉,代码已经合进 main 但运行时不执行。这样做的好处是:主干永远可部署、不存在"长生命分支合并不了"的问题、新功能随时可以打开给部分用户灰度。
# 代码示例
if feature_flag.is_enabled("new_checkout_flow", user=request.user):
return new_checkout(request)
else:
return legacy_checkout(request)适合场景:工程文化成熟的大型团队(Google、Meta 内部)、Feature Flag 基础设施完善、有强大的自动化测试兜底。
缺点:对工程纪律要求极高;Feature Flag 管理有额外成本(flag 过期清理、技术债积累);不适合需要稳定 release 窗口的产品。
四种模型对比#
| 维度 | GitFlow | GitHub Flow | GitLab Flow | Trunk-Based |
|---|---|---|---|---|
| 长期分支数 | 2(main+develop) | 1(main) | 3+(main+各环境) | 1(main) |
| 短命分支 | feature/release/hotfix | feature | feature | 极短命分支或直接主干 |
| 发版频率 | 低(每月/每季) | 中(每天/每周) | 中 | 高(每天多次) |
| CI/CD 成熟度要求 | 低 | 中 | 中 | 高 |
| Feature Flag 依赖 | 不需要 | 可选 | 不需要 | 必需 |
| 复杂度 | 高 | 低 | 中 | 中 |
| 适合团队 | 中大型、版本化产品 | 小中型、Web 服务 | 多环境部署 | 大型、工程文化成熟 |
选型维度#
1. 产品形态#
- 有版本号的客户端软件(App、桌面):GitFlow 或带 release 分支的变体
- 持续部署的 Web 服务:GitHub Flow 或 Trunk-Based
- 多环境部署的服务:GitLab Flow 或 GitHub Flow + 环境分支
2. 团队规模和工程文化#
- 5-15 人小团队:GitHub Flow,简单够用
- 20-100 人中型团队:GitHub Flow + 严格的 PR Review + CI
- 100+ 人大团队 + 强工程文化:Trunk-Based + Feature Flag
- 多个版本并行维护:GitFlow 的 release 分支概念
3. CI/CD 成熟度#
CI/CD 不成熟时,分支策略要"重"——用分支隔离风险,等 CI 兜底。CI/CD 成熟后,分支策略可以"轻"——靠自动化测试和灰度发布兜底,而不是靠分支。
CI/CD 不成熟 ──► GitFlow(分支隔离风险)
│
▼
CI/CD 中等 ──► GitHub Flow / GitLab Flow(PR + CI 检查)
│
▼
CI/CD 成熟 ──► Trunk-Based(主干 + Feature Flag + 灰度)4. 发版节奏#
- 每天多次发版:Trunk-Based 或 GitHub Flow
- 每周发版:GitHub Flow
- 按季度发版:GitFlow
发版节奏和分支策略强相关——选错了会导致"策略和现实不匹配"。比如一个每天发版 3 次的团队用 GitFlow,会被五类分支的维护成本拖垮;反之一个按季度发版的客户端 App 用 GitHub Flow,又缺少 release 准备阶段。
实战建议#
- 大多数中小团队用 GitHub Flow 就够了。如果你的团队同时维护多个版本(比如 SaaS 有企业客户锁定在旧版本),才需要引入 GitFlow 的 release 分支概念。
- 不要教条。这四种模型都是参考,实际落地时常做调整。比如 GitHub Flow + 一个
release/*分支用于发版前 QA,是常见的混合体。 - 分支命名要规范。统一用
type/short-description格式(如feature/user-loginfix/gh-123-null-pointer),全小写、连字符分隔、不超过 50 字符。详见 06 章。 - 短命分支是关键。无论用哪种模型,feature 分支的存活时间都应该尽量短(理想是 1-2 天,最多一周)。长命分支必然积累冲突,最终拖慢整个团队。
- 发版分支流可以独立设计。生产中的真实晋升往往不靠分支,而是靠流水线 stage 串联(同一镜像从 QA → PRE → PROD)。分支做"集成测试",main 做"发布基线",是更贴近现实的模型。
- 验证型需求走独立轨道。有些分支只做验证/预研/demo,明确不上线。这类分支用
exp/spike/poc/前缀,走 PR 隔离环境验证,验完销毁,永不进 main/prod。发版分支流只认feature/fix/这类发版前缀。
小结#
分支策略的本质是回答三个问题:不同类型的工作如何互不干扰、变更如何及时合回主线、历史如何回溯。前两个靠分支模型 + PR 流程,第三个靠 commit message 规范。
没有"最好的分支策略",只有"最适合当前团队的分支策略"。先用 GitHub Flow 起步,遇到瓶颈再演进——这是大多数团队的现实路径。选型时避免两个极端:一是照搬大厂方案(Google 的 Trunk-Based 依赖大量基础设施,小团队学不来),二是完全不做策略(主分支直推、无 PR review,三个月后历史一团乱麻)。下一章讲怎么用 Conventional Commits、Git Hooks、CODEOWNERS 把分支策略落地成自动化规范。