1. 概念
语义化版本规范(SemVer Semantic Versioning
)是 GitHub
起草的一个具有指导意义的、统一的版本号表示规范。它规定了版本号的表示、增加和比较方式,以及不同版本号代表的含义。
在这套规范下,版本号及其更新方式包含了相邻版本间的底层代码和修改内容的信息。语义化版本格式为:主版本号.次版本号.修订号(X.Y.Z
),其中 X
、Y
和 Z
为非负的整数,且禁止在数字前方补零。
Go Modules
使用了语义版本来管理模块。每个语义版本都采用 vMAJOR.MINOR.PATCH
的形式,我们简单介绍下各字段的含义。
2. 规则
版本号可按以下规则递增:
v
:所有版本号都以v
开头。MAJOR
主版本号:意味着有大的版本更新,一般会导致API
和之前版本不兼容。MINOR
次版本号:当做了向下兼容的功能性新增及修改。这里有个不成文的约定需要你注意,偶数为稳定版本,奇数为开发版本。PATCH
修订版本号:用户做了向后兼容的 bug 修复。
你可能还看过这么一种版本号:v1.2.3-alpha
。这其实是把先行版本号(Pre-release
)和版本编译元数据,作为延伸加到了主版本号.次版本号.修订号的后面,格式为 X.Y.Z[-先行版本号][+版本编译元数据]
,如下图所示:
我们来分别看下先行版本号和版本编译元数据是什么意思。
先行版本号意味着,该版本不稳定,可能存在兼容性问题,格式为:X.Y.Z-[一连串以句点分隔的标识符] ,比如下面这几个例子:
1.0.0-alpha
1.0.0-alpha.1
1.0.0-0.3.7
1.0.0-x.7.z.92
编译版本号,一般是编译器在编译过程中自动生成的,我们只定义其格式,并不进行人为控制。下面是一些编译版本号的示例:
1.0.0-alpha+001
1.0.0+20130313144700
1.0.0-beta+exp.sha.5114f85
注意,先行版本号和编译版本号只能是字母、数字,且不可以有空格。
如果两个版本具有相同的主版本号,那么预期更高版本则可以向后兼容较低版本。但是,如果两个版本的主版本号不同,那么它们之间就没有预期的兼容关系。
下面这张图展示了 Go
处理版本更新的方法。my/thing/v2
标识的是特定模块的语义主版本 2。版本 1 是 my/thing
,模块路径中没有明确的版本。但是,当用户引入主要版本 2 或更大版本时,必须在模块名称后添加版本,以区别于版本 1 和其他主要版本,所以版本 2 为 my/thing/v2
,版本 3 为 my/thing/v3
,依此类推。
假设模块 A 引入了模块 B 和模块 C,模块 B 引入了模块 D v1.0.0,模块 C 引入了模块 D v2.0.0。如下所示:
A --> 模块B --> 模块D v1.0.0
A --> 模块C --> 模块D v2.0.0
由于 v1 和 v2 模块的路径不相同,所以他们是互不干扰的两个模块,可以共存。执行 go list
,进一步确认模块 v1 与 v2 是共存的。
~/mathlib(master*) » go list -m all | grep mydiv
github.com/dreamerjackson/mydiv v1.0.1
github.com/dreamerjackson/mydiv/v2 v2.0.1
3. 规范
- 标记版本号的软件发行后,禁止改变该版本软件的内容,任何修改都必须以新版本发行。
- 主版本号为零(
0.y.z
)的软件处于开发初始阶段,一切都可能随时被改变,这样的公共API
不应该被视为稳定版。1.0.0
的版本号被界定为第一个稳定版本,之后的所有版本号更新都基于该版本进行修改。 - 修订号
Z
(x.y.Z | x > 0
)必须在只做了向下兼容的修正时才递增,这里的修正其实就是Bug
修复。 - 次版本号
Y
(x.Y.z | x > 0
)必须在有向下兼容的新功能出现时递增,在任何公共API
的功能被标记为弃用时也必须递增,当有改进时也可以递增。其中可以包括修订级别的改变。每当次版本号递增时,修订号必须归零。 - 主版本号
X
(X.y.z | X > 0
)必须在有任何不兼容的修改被加入公共API
时递增。其中可以包括次版本号及修订级别的改变。每当主版本号递增时,次版本号和修订号必须归零。
4. 如何确定版本号
- 在实际开发的时候,建议你使用
0.1.0
作为第一个开发版本号,并在后续的每次发行时递增次版本号。 - 当我们的版本是一个稳定的版本,并且第一次对外发布时,版本号可以定为
1.0.0
。 - 当我们严格按照
Angular commit message
规范提交代码时,版本号可以这么来确定:
fix
类型的commit
可以将修订号 +1。feat
类型的commit
可以将次版本号 +1。- 带有
BREAKING CHANGE
的commit
可以将主版本号 +1。
5. 伪版本
当我们引入了一个没有用语义版本管理的模块,或者我们希望用某一个特殊的 commit
快照进行测试时,导入模块的版本会是伪版本,例如:v0.0.0-20191109021931-daa7c04131f5
就是一个伪版本。伪版本包含了 3 个部分:
- 基本版本前缀:通常为
vX.0.0
或vX.Y.Z-0
。vX.Y.Z-0
表明该commit
快照派生自某一个语义版本,vX.0.0
表明该commit
快照找不到派生的语义版本; - 时间戳:格式为“yyyymmddhhmmss”,它是创建
commit
的 UTC 时间; - 最后是长度为 12 的
commit
号。
语义版本规范完全说明