简析版本号的规则

一句话概括

语义化版本号的格式为主版本号.次版本号.修订号(x.y.z),递增规则如下

x: 主版本号,做了不兼容的 API 修改

y: 次版本号,做了向下兼容的功能性更新

z: 修订号,一般是向下兼容的 bugfix 和优化

(以下,皆以 x 代表主版本号,y 代表次版本号,z 代表修订号)
img

为什么要版本号

“依赖地狱”问题

大型软件系统往往依赖于众多套件、库,这些依赖关系相当复杂,依赖关系过高会导致版本控制被锁死的问题。想象一下,某一个库依赖于其他库,这些库又依赖于另一些库,那么其中某个库的升级导致的不兼容问题,则会因影响整个系统。依赖关系太松散,则会导致版本的混乱。这就被称之为依赖地狱。

解决方案

一个合理的语义化的版本号约束规则,可以明确版本中的依赖问题。例如 x1.y1.z1 软件依赖于 x11.y11.z11 这个特定版本的库,在库的整个 x11 的主版本,x1 版本的软件可以确保使用正常。这套规则针对于定义的公共 API 而制定:

  • 重大版本更新: x 递增,大量新功能的更新,可能不向下兼容
  • 版本功能更新:y 递增,API 保持向下兼容的新增及修改
  • 版本修订,z 递增,修复问题但不影响 API ,向下兼容

在这套规则约束下,版本号及其更新方式包含了相邻版本间的底层代码和修改内容的信息。

规则

重要程度

  • 必要级: MUST, MUST NOT
    • 使用语义化版本控制的软件必须定义公共 API
    • 标准版本号必须采用 X.Y.Z 格式,数值递增
      • 1.8.1 -> 1.9.0 -> 1.10.0
    • 某版本发行后禁止修改,幂等性地,修改后必须按新版本发行
    • 修订号 Z(x.y.Z | x > 0)在只做了向下兼容的修正时才递增。这里的修正指的是针对不正确结果而进行的内部修改
    • 次版本号 Y(x.Y.z | x > 0)在有向下兼容的新功能出现时递增,任何公共 API 的功能被标记为弃用时也必须递增。每当次版本号递增时,修订号必须归零
    • 主版本号 X(X.y.z | X > 0)必须在有任何不兼容的修改被加入公共 API 时递增。每当主版本号递增时,次版本号和修订号必须归零。
    • 判断版本优先层级时,必须把版本依序拆分为主版本号、次版本号、修订号及先行版本号后进行比较(版本编译信息不在这份比较的列表中)。由左到右依序比较每个标识符号,第一个差异值用来决定优先层级:主版本号、次版本号及修订号以数值比较,例如:1.0.0 < 2.0.0 < 2.1.0 < 2.1.1。当主版本号、次版本号及修订号都相同时,改以优先层级比较低的先行版本号决定。例如:1.0.0-alpha < 1.0.0。有相同主版本号、次版本号及修订号的两个先行版本号,其优先层级“必须 MUST ”透过由左到右的每个被句点分隔的标识符号来比较,直到找到一个差异值后决定:只有数字的标识符号以数值高低比较,有字母或连接号时则逐字以 ASCII 的排序来比较。数字的标识符号比非数字的标识符号优先层级低。若开头的标识符号都相同时,栏位比较多的先行版本号优先层级比较高。
      • 范例:1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0- rc.1 < 1.0.0。
  • 应该级:REQUIRED, SHALL, SHALL NOT

    • 主版本号为零(0.y.z)的软件处于开发初始阶段,一切都可能随时被改变。这样的公共 API 不应该被视为稳定版
    • 1.0.0 的版本号用于界定公共 API 的形成。这一版本之后所有的版本号更新都基于公共 API 及其修改内容。
    • 当判断版本的优先层级时,版本编译信息应该被忽略。因此当两个版本只有在版本编译信息有差别时,属于相同的优先层级。
  • 选项级:MAY、OPTIONAL

    • 次版本号 Y(x.Y.z | x > 0)在内部程序有大量新功能或改进被加入时递增,也可以包括修订级别的改变
    • 主版本号可以包括次版本号及修订级别的改变。
    • 先行版本号被标注在修订版之后,先加上一个连接号再加上一连串以句点分隔的标识符号来修饰。标识符号必须由 ASCII 码的英数字和连接号 [0-9A-Za-z-] 组成,且禁止留白。数字型的标识符号禁止在前方补零。先行版的优先级低于相关联的标准版本。被标上先行版本号则表示这个版本并非稳定而且可能无法达到兼容的需求。
      • 范例:1.0.0-alpha、1.0.0-alpha.1、1.0.0-0.3.7、1.0.0-x.7.z.92。
    • 版本编译信息可以被标注在修订版或先行版本号之后,先加上一个加号再加上一连串以句点分隔的标识符号来修饰。标识符号必须由 ASCII 的英数字和连接号 [0-9A-Za-z-] 组成,且禁止留白。
      • 范例:1.0.0-alpha+001、1.0.0+20130313144700、1.0.0-beta+exp.sha.5114f85。

一些建议

  • 0.y.z 初始开发阶段,最好以 0.1.0 作为原始开发版本
  • 快速开发和迭代时期,此时主版本号应该为 0
  • 软件被用于正式环境即是 1.0.0 版本的最佳时机
  • 不要为了语义化版本号而语义化,它是为了开发迭代服务的
  • 谨慎对待不兼容的大版本(即主版本号级别)升级
  • 处理启用的更新之前,保留一个次版本,该版本应具有弃用信息