2. Git 分支策略:主分支、开发分支、发布分支、热修复分支的协作模型

分支策略这东西,说白了就是团队怎么在 Git 里「并道行驶」。我见过太多项目,一开始没规划好,最后合并时冲突堆成山,发布窗口一拖再拖。今天聊的这套模型,是我在多个全量包项目中反复打磨过的,核心就四个分支类型。

2.1 四个核心分支,各司其职

先看一张整体结构图,后面我们再逐个拆解。

Git 分支协作模型总览 main(主分支) develop(开发分支) release/*(发布分支) hotfix/*(热修复分支) feature/*(功能分支) personal/*(个人分支) 说明:箭头方向表示「合并来源 → 目标分支」 feature 和 personal 分支从 develop 拉出,合并回 develop;release 和 hotfix 从 develop 拉出,合并回 main 和 develop

2.2 main 分支:永远可部署

main 分支只有一个铁律:任何时候 checkout 出来,代码都是可部署的。我在项目中遇到过有人直接往 main 上 push 未测试的代码,结果线上回滚了三次。从那以后,我强制 main 分支只能通过 Pull Request 合并,而且必须经过 CI 全量流水线。

核心原则:main 分支的每一次提交,都应该对应一个可追溯的版本号。全量包制作时,直接从 main 打 tag 拉取代码,不要从其他分支拉。

2.3 develop 分支:日常集散地

develop 是团队日常工作的主干。所有功能分支、个人分支都从这里拉出,开发完再合并回来。说白了,这就是大家的「碰头点」。

我个人习惯在 develop 上开启 CI 的「轻量级检查」——只跑单元测试和代码规范,不跑全量集成测试。为什么?因为 develop 变化太快,全量跑一遍要 40 分钟,太浪费。全量测试留给 release 分支去做。

小技巧:develop 分支建议设置「线性历史」策略,禁止 merge commit,只允许 squash merge 或 rebase。这样历史干净,回查问题时一目了然。

2.4 release 分支:发布前的质检站

当 develop 的功能攒够一个发布周期,就从 develop 拉出 release 分支。命名规则我推荐 release/v1.2.3 这种格式,版本号一目了然。

release 分支上只做三件事:

  • Bug 修复——只修不增,严禁加新功能
  • 版本号更新——全量包的版本文件、CHANGELOG 都在这里定稿
  • 全量回归测试——跑完整的集成测试、性能测试、安全扫描

我记得有一次,团队在 release 分支上发现一个内存泄漏,修完后忘记合并回 develop。结果下一个版本又出现了同样的问题。嗯,这里要注意:release 分支的修复,必须双向合并——合并到 main 打 tag,同时合并回 develop。

警告:release 分支的生命周期应该很短,一般不超过 3 天。拖太久,develop 上的新代码和 release 的差异越来越大,合并时冲突会让人崩溃。

2.5 hotfix 分支:线上救火队

线上出了紧急 Bug,等不了下一个发布周期。这时候从 main 分支(注意,不是 develop)拉出 hotfix/2.3.1 分支。

为什么从 main 拉?因为 main 上的代码是当前线上运行的版本,修复基线最准确。如果从 develop 拉,可能混入了还没上线的功能,修复完反而引入新问题。

hotfix 的流程我总结为三步:

  1. 从 main 拉出 hotfix 分支,修复代码
  2. 合并回 main,打上补丁版本 tag(如 v2.3.1)
  3. 合并回 develop,确保下一个版本也包含这个修复

避坑指南:我曾经在 hotfix 合并时只合并了 main,忘了合并 develop。结果两周后发新版本,那个 Bug 又出现了。后来我写了个 Git 钩子,每次 hotfix 合并到 main 后自动创建合并到 develop 的 PR,才彻底解决。

2.6 feature 与 personal 分支:开发者的工作台

这两个分支是开发者的私人空间。feature 分支对应一个完整功能,personal 分支对应个人日常开发。我建议团队统一前缀:feature/order-system、personal/zhangsan/daily。

它们都从 develop 拉出,开发完成后合并回 develop。这里有个容易踩的坑:feature 分支不要跨度过大。一个 feature 分支如果开发超过 5 天,建议拆分成子任务,或者每天 rebase 一次 develop,否则合并时冲突量会指数级增长。

分支类型 拉出源 合并目标 生命周期 CI 级别
main — — 永久 全量流水线
develop — — 永久 轻量检查
release/* develop main + develop ≤ 3 天 全量回归
hotfix/* main main + develop ≤ 1 天 全量 + 紧急
feature/* develop develop ≤ 5 天 功能级
personal/* develop develop ≤ 1 天 无/手动

2.7 全量包制作中的分支选择

最后聊一个实战问题:做全量包时,到底从哪个分支拉代码?

我的答案是:永远从 main 分支的 tag 拉。不要从 develop 拉,不要从 release 拉。因为 main 上的每个 tag 都对应一个经过全量测试、已经上线的版本,可追溯、可回滚。

如果非要做一个「预发布全量包」用于灰度测试,可以从 release 分支拉,但必须在包名或元数据里标注 -rc(Release Candidate),让所有人知道这不是正式版本。

个人经验:我习惯在全量包制作脚本里加一个检查步骤——自动验证当前代码是否来自 main 分支的 tag。如果不是,直接报错退出。这个检查帮我拦截过至少 5 次「拿错分支打全量包」的失误。