我们常用的语义版本控制
版本号由三部分组成:MAJOR.MINOR.PATCH
。
MAJOR
:进行不兼容的 API 更改时递增。
MINOR
:以向后兼容的方式添加功能时递增。
PATCH
:进行向后兼容的错误修复时增加。
比如 v1.2.3
,1
是主版本,2
是次要版本,3
是修订版本。
但是最近在浏览各种项目时,注意到开源社区的一些关注度较高(几十K的start)的项目都出现了一种如图所示的奇怪的版本号控制方案的转变:从v0.XX.Y 转变为vXX.Y.Z。
后来了解到这是由开源社区的Anthony Fu提出的一种新的语义版本控制方案:
版本号= {100 * EPOCH + MAJOR} .MINOR.PATCH
EPOCH:当您进行重大或突破性更改时增加。
MAJOR:当您进行较小的不兼容 API 更改时递增,MAJOR取值范围为0-99。
MINOR:当您以向后兼容的方式添加功能时递增。
PATCH:当您进行向后兼容的错误修复时增加。
为什么会提出这种设计,是因为在目前主流的版本号控制中,我们倾向于将 v2.0 到 v3.0 视为一个巨大的、突破性的变化,但是我们可能只是引入了一个少量的不兼容特性;此外,当版本号较大时, v125.0 到 v126.0 则不容易让人感知到巨大的、突破性的变化(例如当前的Google Chrome浏览器,版本已经达到@^137.x ,但是很少有用户们去 升级新版本的浏览器)。
antfu提到这种新的版本控制:“如果对核心进行重大的不兼容修改,我们可以直接跳转到 v100.0.0 以标志着新时代的到来并发布重大公告。我建议为每个非零 EPOCH 分配一个代码名称,以使其更容易记住且更易于引用。这种方法为维护人员提供了更大的灵活性,可以有效地向用户传达更改的规模。”
目前较已有slidevjs, unocss,taze, ni等多个开源项目都转移到了这种版本控制。
在我看来,其实可能并不是规则本身有问题,而是很多人没有严格按照规则来用这个版本系统。例如:按道理来说,只有在出现重大变更、破坏性改动的时候才应该升级大版本号。但实际上呢?有些人功能没改好、全是bug,却已经升了好几个大版本。这就导致大版本号一开始就被人滥用,搞得大家对“breaking change”“重大破坏性更新”这件事麻木了。
同样的道理,如果这个新的时代版本号也被滥用,那 100100 和 100200 看起来是不是也挺“兼容”的?反正用户都已经习惯了无视这些数字了。
我觉得严格遵守语义化版本规则仍然是有效的,例如:
- 在 0.x 阶段,专注于功能验证、优化和打磨。
- 到了 1.x,才正式投入生产使用。
- 那 1.x 之后如果有新功能需要测试,那也还有很多其他的方式可以用,比如内测版、公测版、预发布版等标签(tag)。每个 tag 后面还可以加数字,表示不同的测试阶段。
总之,只要不滥用大版本号,用户的感知应该也不会被削弱,也能更清楚地理解每次更新的意义。