语义化版本管理

语义化版本管理是基于语义化版本号的版本管理规范。该规范约定了版本号的格式,升级版本号的要求等。 该规范着重强调了公开接口兼容性管理的要求,软件的公开接口需要有明确严格的文档或代码描述。 对于遵守该规范的软件包,用户根据其版本号就能知道新包是否与当前的版本兼容。这对于软件依赖包的升级管理非常重要。 因为引入不兼容的新包会导致应用出现问题。软件的模块化提供了大量可重用的软件包,极大提高了软件开发质量和效率,同时也带来了软件包依赖管理的困难。 语义化版本是简化软件包依赖管理的有效规范。

语义化版本规范约定的基本版本号格式为:

主版本号.次版本号.修订号

版本号升级的规则为:

  1. 主版本号:当新功能或修改导致接口不兼容的时候
  2. 次版本号: 当新增功能是向下兼容的时候
  3. 修订号: 当做了向下兼容的问题修复

主版本号升级后,次版本号和修订号重置为零。次版本号升级后,修订号重置为零。

在此基础上,可以再加上预备发布版本号, 比如 1.0.0-alpha.1, 1.0.0-beta.2。 预备版本号在版本依赖上的优先级低于其正式版本号, 比如1.0.0-alpha.1比 1.0.0要旧。

在此基础上,可以再加上编译信息, 比如 1.0.0-alpha.1+901

需要注意的是,语义化版本的约定并不是强制性的,而各种语言的包管理规范及工具往往有更详细的约定, 而且其格式可能和语义化版本约定不同,但基本的内涵是相似的。 比如预备发布版本号在Python的PEP 440中约定的字符名称是a, b, rc。a代表alpha,b代表beta, rc代表Release Candidate, 而且正式版本号与预备版本号之间没有分隔符。比如应该写成1.0.0a1, 而不是1.0.0-a.1。

软件包依赖表达式

基于语义化版本号,很多语言的包管理工具都提供了灵活的包依赖表达式。 所谓灵活的包依赖表达式,指的在严格相同的版本外,也支持一定范围内的版本变动。

Python包依赖管理

PEP 440PEP 508 约定了Python的版本号规则。以pip为例,比如应用依赖requests包版本2.4.3, 那么依赖可以表达为

#严格匹配
requests, ==2.4.3

#大约匹配
requests, ~=2.4.3

#大版本号匹配
requests, >=2.4.3,<3.0.5,!=3.0.1

更全面的写法请参考 pip requirements 文件格式

Java包依赖管理

Maven和Gradle是流行的Java项目管理工具,都包含了依赖管理能力。当前版本的Maven所支持的版本号 在我们常见的例子里面,似乎是严格匹配的。然而并不是。直接写版本号,那是一种 soft requirements。 Maven使用了一种类似数学集合范围的表达式。即小括号表示范围不包括,中括号表示范围包括。

(1.0, 2.0] ==> 1.0 < x <= 2.0 [1.1] ==> x == 1.1 1.1 ==> x = 1.1 if all other conditions are met.

See: http://maven.apache.org/pom.html, "Dependency Version Requirement Specification".

PHP包依赖管理

Composer是PHP流行的包依赖管理工具。Composer在指定版本号时支持指定范围。CSDN上的 这篇文章 详细介绍了如何使用composer.json来约定依赖包。

Node.js包依赖管理

请参考 http://www.u396.com/semver-range.html

参考资料

  1. tuicool上的语义化版本文章 http://www.tuicool.com/articles/JnmuE3R
  2. 语义化版本规范 http://semver.org/lang/zh-CN/