代码分支管理策略
# 代码分支管理策略
GitFlow/Trunk-based、cherry-pick——分支策略决定协作效率
# 一、分支策略不是选哪个好看——是选哪个不痛苦
两种主流策略的本质对比:
GitFlow:
master ────┬───────┬──── (生产代码)
│ │
develop ───┼──┬──┬─┼──┬── (开发主线)
│ │ │ │ │
feature/A ┘ │ │ │ │ (功能分支,从 develop 拉,合回 develop)
feature/B ┘ │ │ │
release/1.2 ┘ │ │ (发布分支,从 develop 拉,合到 master + develop)
hotfix/1.2.1 ┘ │ (热修复,从 master 拉,合到 master + develop)
Trunk-based(主干开发):
main ──┬─────┬─────┬───── (唯一的长期分支)
│ │ │
feat/A─┘ │ │ (短功能分支,最多存在 1-2 天)
feat/B───────┘ │
feat/C─────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 选型决策
| 场景 | 推荐策略 | 原因 |
|---|---|---|
| 5 人以下小团队,每天发版 | Trunk-based | 分支少,合并快,最简洁 |
| 10-50 人,有固定发布周期 | 简化 GitFlow(不要 develop) | 去掉 develop 层,master + feature + release |
| 维护多个版本(如 v1.x 有客户用,v2.x 在开发) | 完整 GitFlow | release 和 hotfix 分支能管理多版本并行 |
| 开源项目,外部贡献者多 | GitHub Flow(Trunk-based 变体) | 所有 PR 往 main 提,靠 CI + Review 保证质量 |
90% 的团队不需要 GitFlow 的全部复杂性。 如果你从未同时维护过 3 个以上活跃版本——你在用一个你不需要的复杂度。
# 二、简化 GitFlow——只保留四个分支类型
master :生产代码。只接受 release 和 hotfix 的合并。
feature/* :新功能。从 master 拉,合回 master。(活 1-5 天)
release/* :发布候选。从 master 拉,修 bug 后合回 master + tag。
hotfix/* :紧急修复。从 master 拉,修完合回 master + tag。
1
2
3
4
2
3
4
去掉 develop 分支:develop 在大多数团队的真正作用是"延迟合并到 master 的缓冲区"。如果你有 CI + code review ——合到 master 就是安全的,不需要 develop 来缓冲。
# 三、合并策略——merge vs rebase vs squash
Merge(保留完整历史):
master: A → B → C → M (M 是 merge commit)
feature: D → E ────┘
→ 分支结构清晰,但历史里有很多分叉
Squash and Merge(把整个 feature 压成一个 commit):
master: A → B → C → D' (D' 包含了 D+E 的全部改动)
→ master 历史是干净的线性,但丢了 feature 内部的细分 commit
Rebase and Merge(线性历史,保留细分):
master: A → B → C → D → E (D 和 E 被挪到了 C 后面,hash 变了)
→ 历史干净,但 rebase 有风险(多人协作同一个 feature 分支时会翻车)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
实战选择:
对 master 分支:永远只用 Merge 或 Squash Merge —— 不要 rebase master
对 feature 分支:
你一个人在做 → rebase 到 master 再提 PR(保持线性历史)
多人在做 → merge master 进 feature(安全,不改变已推送的 commit)
1
2
3
4
2
3
4
# 四、cherry-pick ——能用但不要滥用
cherry-pick 是把一个 commit 单独挑出来,嫁接到另一个分支上。听起来很灵活——但那是因为你不知道它有多危险。
cherry-pick 能用的场景:
→ 在 release/1.2 上修了一个 bug,需要同步到 master
→ 从 release 分支 cherry-pick 这个 fix commit 到 master
cherry-pick 不该用的场景:
→ "我只想上线 feature 的一半,另一半下次再说"
→ cherry-pick 了 commit A 但没 pick commit B(A 依赖 B)
→ 上线后报错,原因是你只搬了代码没搬它的前置修改
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
规则:如果同一个 bug fix 需要放到多个分支——cherry-pick。如果同一个功能要拆成两部分上线——不要 cherry-pick,用 Feature Flag 控制。
# 五、分支命名的约定
feature/user-login → 功能分支
bugfix/fix-payment-null → bug 修复分支
hotfix/2024-01-15-crash → 紧急修复(带上日期)
release/1.3.0 → 发布分支
chore/update-deps → 杂务(升级依赖、改 CI 配置等)
1
2
3
4
5
2
3
4
5
命名铁律:分支名字一看就知道它在做什么,删除时不犹豫。三个月后你看到 fix-bug 和 fix-payment-timeout-on-null-user —前者你敢删吗?不敢,因为你不知道它修的是什么。
# 六、分支保护的底线配置
master 分支必配的保护:
□ 禁止直接 push(必须通过 PR)
□ 至少 1 个人 approve 才能合并
□ CI 必须通过(自动化测试全绿)
□ PR 必须和 master 无冲突(冲突需要手动 rebase/merge 解决)
□ 不允许 force push
可选的加强:
□ 特定目录的改动需要特定人员 approve(如 db/migrations/ 需要 DBA 审批)
□ PR 标题必须符合 conventional commits 格式
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
为什么需要分支保护:不是不信任同事——是深夜 2 点你觉得"就改一行直接 push 吧",第二天早上线上挂了,没人知道你改了哪一行。
# 七、小结
分支策略选择:
小团队、快迭代 → Trunk-based(只有一个 main 分支)
中大型团队 → 简化 GitFlow(master + feature + release + hotfix)
多版本并行维护 → 完整 GitFlow
三条铁律:
1. Master 分支永远可部署——任何合入 master 的代码都应该能随时上线
2. 分支命名一眼可辨——feature/ 、bugfix/ 、hotfix/ 前缀 + 简短描述
3. Cherry-pick 只用于跨分支同步 fix,不用于拆分功能上线
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
行动清单:
- [ ] 打开仓库的 Settings → Branches → 检查 master 有没有保护规则
- [ ] 数一下当前仓库有多少个活跃分支——超过 20 个?删掉那些超过 2 周没更新的
- [ ] 团队对齐:用的是 merge commit 还是 squash?所有人都同意同一个规则吗?
上次更新: 2026/06/15, 14:32:53