版本控制与分支策略:Git Flow、Trunk Based Development、语义化版本控制、Changelog 管理

版本控制这件事,说白了就是给代码上「后悔药」。但光有后悔药还不够,你得知道什么时候该吃哪一颗。我在企业级 SDK 项目里踩过不少坑,今天就把这些经验掰开揉碎了讲给你听。

一、分支策略:两条主流路线

分支策略没有银弹。我见过团队死磕 Git Flow,也见过团队用 Trunk Based 玩得飞起。关键看你的发布节奏和团队规模。

1. Git Flow:适合固定周期发布

Git Flow 把分支分成了五类:master、develop、feature、release、hotfix。结构清晰,但分支多了也容易乱。

核心原则:master 只存可发布的代码,develop 是集成分支,feature 从 develop 拉出,release 用于发布前准备,hotfix 从 master 拉出并合并回两边。

我在做 SDK v2.0 时用过这套。当时团队 15 人,每两周发一个版本。流程是这样的:

  1. 从 develop 拉 feature/xxx 分支开发新功能
  2. 开发完合并回 develop,跑集成测试
  3. 准备发布时,从 develop 拉 release/2.0.0
  4. release 分支上只修 bug,不添新功能
  5. 测试通过后,合并到 master 并打 tag
  6. 再把 release 合并回 develop,避免遗漏

我的习惯:release 分支的生命周期不要超过一周。拖太久,develop 和 release 的差异会越来越大,合并时容易出冲突。

2. Trunk Based Development:适合持续交付

Trunk Based 就简单多了——所有人往主干(trunk/main)提交,通过特性开关控制功能是否生效。分支存活时间不超过一天。

我曾经在微服务 SDK 团队推行过这个模式。团队 8 个人,每天发布 3-5 次。说实话,刚开始大家很不适应,总觉得「直接往主干推代码太危险了」。但配合上充分的单元测试和代码审查,其实比 Git Flow 更省心。

对比维度 Git Flow Trunk Based
分支数量 多(5+ 种) 少(1-2 种)
发布频率 低(周/月) 高(天/小时)
冲突风险 低(隔离好) 高(需频繁合并)
适合场景 固定版本、多环境 持续交付、快速迭代

避坑指南:我曾经见过一个团队,Git Flow 用了半年,release 分支上修了 30 多个 bug,最后合并回 develop 时冲突了整整两天。如果你发现 release 分支上的修改越来越多,说明你的发布周期太长了。

二、语义化版本控制:SDK 的身份证

语义化版本控制(SemVer)不是新东西,但很多 SDK 团队用错了。格式很简单:主版本号.次版本号.修订号。但什么时候该升哪一位,很多人拿不准。

规则:

  • 修订号(Patch):向下兼容的 bug 修复
  • 次版本号(Minor):向下兼容的新功能
  • 主版本号(Major):不兼容的 API 变更

举个例子。我维护过一个 HTTP 客户端 SDK,v1.2.3 版本。某天发现连接池泄漏,修了之后发 v1.2.4。后来加了请求重试功能,API 没变,发 v1.3.0。再后来把 send() 方法的参数类型改了,这就得发 v2.0.0。

但现实往往更复杂。你想想看,如果只是改了个内部实现,对外 API 完全不变,但性能提升了 10 倍,该升哪一位?我个人习惯升次版本号,因为虽然 API 没变,但行为有显著变化,用户应该知道。

# 版本号示例
v1.2.3 → v1.2.4  # 修 bug
v1.2.3 → v1.3.0  # 加功能
v1.2.3 → v2.0.0  # 改 API
v1.2.3 → v1.2.3-alpha.1  # 预发布
v1.2.3 → v1.2.3+build.20240301  # 构建元数据

我的建议:预发布版本用 -alpha、-beta、-rc 后缀。比如 v2.0.0-rc.1,表示候选发布版。这样用户知道这个版本还不稳定,但可以提前测试。

三、Changelog 管理:写给用户的说明书

Changelog 不是给开发者看的,是给 SDK 使用者看的。我见过太多 Changelog 写成「修复了一些 bug」「优化了性能」,用户看了等于没看。

好的 Changelog 应该按版本分组,每个版本下分几个类别:

  • Added:新功能
  • Changed:功能变更
  • Deprecated:即将废弃的功能
  • Removed:已移除的功能
  • Fixed:bug 修复
  • Security:安全更新

我曾经接手过一个 SDK,Changelog 里全是「更新依赖」「重构代码」。用户根本不知道升级后会不会出问题。后来我强制要求:每个 PR 必须附带 Changelog 条目,否则不能合并。

# Changelog 示例

## [2.0.0] - 2024-03-01

### Added
- 新增批量请求接口 `batchSend()`
- 支持自定义超时时间

### Changed
- `send()` 方法参数从 `(String, Map)` 改为 `(RequestConfig)`
- 日志级别从 DEBUG 改为 INFO

### Removed
- 废弃的 `sendSync()` 方法已移除

### Fixed
- 修复连接池泄漏问题 (#142)
- 修复重试时请求体丢失的问题 (#158)

避坑指南:我曾经见过一个团队,Changelog 里写「修复了若干问题」。用户升级后出了新 bug,根本不知道是不是这次升级导致的。记住:Changelog 要具体,要可追溯,最好带上 issue 编号。

四、知识体系总览

下面这张图把版本控制、分支策略、版本号、Changelog 的关系串起来了。你仔细看,它们不是孤立的,而是一个完整的发布链路。

SDK 版本控制与发布流程 分支策略 语义化版本 Changelog 管理 Git Flow Trunk Based 主版本号 次版本号 修订号 Added / Changed Deprecated / Removed Fixed / Security 核心逻辑 分支策略决定代码如何组织 → 版本号标识每次发布 → Changelog 记录变更内容

五、实战建议:把这些串起来

光知道理论没用,得能落地。我总结了几条实战经验:

  • 分支策略选一种,别混用。我见过团队 Git Flow 和 Trunk Based 各用一半,结果分支乱成一锅粥。
  • 版本号自动化。用 CI/CD 工具自动打 tag,别手动操作。我习惯在合并到 master 时触发版本号递增。
  • Changelog 从 PR 描述生成。让开发者在 PR 里写清楚变更类型和描述,合并时自动追加到 Changelog 文件。
  • 发布前做一次版本号检查。确保 package.json(或等价文件)里的版本号和 git tag 一致。

我的习惯:每次发布前,我会跑一个脚本,检查 Changelog 里最新版本是否和 git tag 匹配,不匹配就拒绝发布。这个小工具帮我避免过至少 5 次发布事故。

嗯,版本控制这件事,说白了就是给 SDK 的每一次变化留下痕迹。分支策略管代码怎么流动,版本号管怎么标识,Changelog 管怎么告诉用户。这三者配合好了,你的 SDK 发布流程就稳了一大半。