关于语义化版本

每个语言都有自己的包管理工具,例如php的composer,nodejs的npm,golang的glide等等。他们对于包的版本控制都遵循语义化版本。

版本格式:主版本号.次版本号.修订号,版本号递增规则如下: 主版本号:当你做了不兼容的 API 修改, 次版本号:当你做了向下兼容的功能性新增, 修订号:当你做了向下兼容的问题修正。 先行版本号及版本编译信息可以加到“主版本号.次版本号.修订号”的后面,作为延伸。

对于大部分的包管理工具,我们在进行包依赖控制的时候通常会有集中写法,下面以composer为例,

不限版本

1
2
3
"require": {
"packagename": "*"
}

这样做的话 composer 将根据你的 minimum-stability 配置来决定是使用最新的 dev 版本还是 stable 版本。

直接使用版本号

1
2
3
4
"require": {
"packagename": "1.2.3",
"packagename": "=1.2.3"
}

composer 将永远使用这个版本而不考虑版本的更新。

使用 ~ 约束符锁定最小版本

这里说的最小版本是相对的,看下面几个例子。

1
2
3
4
"require": {
"packagename1": "~1.2" # 次版本号锁定,代表 >= 1.2 并且 <= 2.0
"packagename2": "~1.2.1" # 修订号锁定,代表 >= 1.2.1 并且 <= 1.3
}

使用 ^ 约束符锁定最大版本

这个约束符的作用是锁定主版本号,看下面几个例子。

1
2
3
"require": {
"packagename": "^1.1" # 主要主版本是1的都可以,例如1.2.1,1.99.9999
}

这里要补充一个特殊的情况,例如我们这样写,

1
2
3
"require": [
"packagename": "^0.17.1" # >= 0.17 并且 <= 0.18
]

这个包的大版本号为0,则^的行为与~相同,这是因为此时处于开发阶段,即使是次要版本号变动,也可能带来程序的不兼容。

锁定版本范围

我们也可以使用一些范围约束符(>,<,>=,<=,|)来限定版本,看下面几个例子。

1
2
3
4
5
6
7
"require": {
"packagename1": ">5.0",
"packagename2": ">=5.0",
"packagename3": "<6.0",
"packagename4": ">=1.3 | >=1.7",
"packagename5": "^5.6|^7.0", # 5.x.x版本或者7.x.x版本
}

使用 dev 前缀加分支名

这个经常在开发环境下使用,例如 dev-master 就是代表 master分支,dev-xxx 就是代表 xxx 分支。

最后,引入 semver.org 官网的一句话。

记住, 语义化的版本控制就是透过版本号的改变来传达意义。若这些改变对你的使用者是重要的,那就透过版本号来向他们说明。