版本管理体系

版本管理这事儿,说简单也简单,说复杂能让你头疼好几天。我见过不少团队,刚开始随便写个版本号,等 SDK 一发布,用户就开始骂娘——为什么新版本把我的旧接口删了?为什么这个版本不能降级?归根结底,就是没把版本管理当回事。

今天咱就聊聊怎么搭一套靠谱的版本管理体系。核心就三块:语义化版本(SemVer)、API 兼容性定义、以及 SDK 版本策略。

语义化版本(SemVer)

SemVer 的规则其实就一句话:主版本号.次版本号.修订号(MAJOR.MINOR.PATCH)。但很多人只记住了格式,没理解背后的含义。

  • 主版本号(MAJOR):当你做了不兼容的 API 修改。说白了,就是用户得改代码才能用新版本。
  • 次版本号(MINOR):向下兼容的新功能。用户升级后,旧代码还能跑,但能体验新东西。
  • 修订号(PATCH):向下兼容的问题修复。仅改 bug,不增加任何新能力。

我个人习惯在每次发布前,先问自己三个问题:
(1)这次有没有破坏用户现有代码?
(2)有没有新增公开 API?
(3)是不是只修了 bug?
然后对号入座。

小技巧:在 0.x.y 阶段(比如 0.1.0),可以随意变更不兼容接口,但一定要在文档里标注清楚。我见过项目在 0.x 阶段直接跳主版本,反而把用户搞懵了。

我曾经接手过一个 SDK,版本号从 1.23.0 直接跳到 2.0.0,结果发现只是改了一个内部日志级别……这就是典型的滥用主版本号。用户一看 2.0.0,以为天塌了,其实啥也没变。

API 兼容性定义

先搞清楚三个概念,这是版本管理的基石。

类型 定义 例子
向后兼容 新版本 SDK 能完全替换旧版本,用户代码无需修改。 旧版 getUser(id) 返回一个对象,新版返回相同结构的对象+新增字段。
向前兼容 旧版本 SDK 能处理新版本客户端发来的数据(通常指数据格式容错)。 新版客户端增加了一个可选字段,旧版服务端能忽略该字段继续正常工作。
中断性变化 升级后用户代码必须修改,否则编译或运行时出错。 删除方法 getUser(id),改为 fetchUser(id);改变方法签名;移除旧枚举值。

你想想看,在 SDK 世界里,向后兼容 是最重要的。用户升级你的库,最怕的就是“啊,我的代码编译不通过了”。所以每次改动 API 时,我都会问:这个变化能被旧调用者无感接受吗?

向前兼容则更多体现在通信协议或序列化格式上。我记得有一次给 Secrets SDK 加了一个 metadata 字段,后端直接忽略旧客户端不传这个字段的情况——这就是向前兼容。但如果你把旧字段改名,那就不兼容了。

注意:修改枚举值、调整方法参数类型、或者把可选参数变成必填,都是典型的中断性变化。这些一定要标红。

SDK 版本策略

有了 SemVer 和兼容性定义,还得有一套实际的版本策略。我总结了几条硬规矩:

  1. 每次发布都必须更新版本号,哪怕只是改了 readme。不要攒了一堆改动才发一个版本,否则用户根本不知道哪个版本包含了哪个修复。
  2. 主版本号升级时,必须提供迁移指南。我曾经犯过这个错——直接发了 2.0.0 的 jar 包,用户一脸懵逼:我该怎么从 1.x 迁移?后来不得不连夜写文档。
  3. 次版本号内不要引入任何不兼容变化。如果实在不小心引入了,立刻 rollback,或者发一个紧急主版本。
  4. 修订号只能修 bug,不新增 API、不改签名。哪怕修 bug 导致行为变化,但只要输入输出一致,就属于 PATCH。但如果修 bug 导致原本能运行的代码报错,那就是不兼容,得升主版本。

另外,对于 Pre-release 版本(比如 2.0.0-alpha.1, 2.0.0-beta.2),我建议严格限制使用场景。只在内部测试或给早期尝鲜者用,且必须标注“不保证兼容性”。用户一旦用了 Pre-release,就要自己承担风险。

核心原则:版本号是契约。每次变更都要想清楚,这个版本是“无忧升级”还是“需要动手”。

我还会用一张决策流程图来帮团队快速决定版本号。下面这张图就是咱们课程的核心——版本号决策流程。

版本号决策流程 SDK 版本号决策流程 是否修改公开 API? 否 → 只是修 bug? 是 → 升 PATCH 否 → 升 MINOR 是否向下兼容? 兼容 → 升 MINOR 不兼容 → 升 MAJOR 记忆口诀 MAJOR:天灾(改接口,用户代码必改) MINOR:人祸(加功能,用户代码不动) PATCH:小修(修 bug,用户睡大觉)

这张图我贴在团队白板上好多年了。每次有人问“这个改动该升什么版本”,我就让他对着图走一遍。基本不出错。

最后说一个实用技巧:版本号不要跳着升级。比如从 1.2.3 直接跳到 2.0.0,中间得说明为什么跳过 1.3.x 和 1.4.x。用户会怀疑你是不是偷偷藏了不兼容变化。我一般会在 CHANGELOG 里清晰列出每个版本的变化,哪怕只是改了个 typo。

总结:版本管理就是做三层事——
• 用 SemVer 定规矩
• 用兼容性定义判断变化性质
• 用版本策略落地执行
三者缺一不可。