本文目录导读:

开源项目遵循语义化版本控制(SemVer,Semantic Versioning),核心目的是通过版本号清晰传达兼容性变化,它采用 主版本号.次版本号.修订号 的格式,并遵循以下规则:
核心规则
格式为:MAJOR.MINOR.PATCH(5.1)。
-
主版本号 (
MAJOR): 当你做了不兼容的 API 修改时递增。- 用户视角:升级到新主版本,代码很可能需要修改,现有功能可能无法正常工作。
- 常见场景:
- 删除或重命名公开的函数、类、方法。
- 修改函数参数类型或返回值类型。
- 修改数据库表结构且不提供迁移。
- 配置项语法或含义变化。
-
次版本号 (
MINOR): 当你以向后兼容的方式添加功能时递增。- 用户视角:可以安全升级,新功能可用,旧代码不受影响。
- 常见场景:
- 添加新的公开 API(函数、类、方法)。
- 为现有功能增加可选参数。
- 引入向后兼容的新配置项。
- 标记某些旧功能为“废弃”(deprecated),但暂时保留。
-
修订号 (
PATCH): 当你做了向后兼容的缺陷修复时递增。- 用户视角:可以安全升级,修复了 bug,无新功能。
- 常见场景:
- 修复导致崩溃、错误结果的安全漏洞。
- 修复文档错误。
- 提高性能(不改变外部行为)。
特殊版本与版本范围
-
预发布版本: 用 连接预发布标签。
0.0-alpha.1,0.0-beta.3,0.0-rc.1。- 规则:预发布版本优先级低于其对应的正式版本。
- 使用场景:在正式大版本发布前,用于测试、收集反馈(Alpha 内测、Beta 公测、RC 候选版)。
- 注意:用户应谨慎使用预发布版本,其 API 可能不成熟。
-
构建元数据: 用 连接构建信息。
0.0+build.20240101。- 规则:构建元数据不影响版本优先级比较。
- 使用场景:标识不同的构建环境(如 CI 构建编号)。
项目实践中需要遵守的关键点
-
明确公共 API: 项目必须明确定义并声明其公共 API,所有遵循 SemVer 的变更都基于这个公共 API。
- 怎么做:
- 在文档(如
README.md,文档站点)中明确哪些是公共API。 - 对于库,通常导出给用户使用的就是公共API。
- 内部模块、私有函数不属此列,可以随时修改。
- 在文档(如
- 示例:一个 Python 包在
__init__.py中通过__all__导出的函数和类是公共 API,其他下划线开头的函数是内部的。
- 怎么做:
-
版本号递增规则:
- 初始开发阶段:通常从
1.0开始,在x.y阶段,主版本号为 0,API 不稳定,任何变化都可能不兼容。 - 正式发布 (1.0.0):当项目 API 稳定且被用于生产环境时,发布
0.0。 - 递增顺序:
- 修复 bug 后:
0.0->0.1 - 新增向后兼容功能后:
0.1->1.0 - 做了不兼容修改后:
1.0->0.0
- 修复 bug 后:
- 初始开发阶段:通常从
-
依赖项管理:
- 在语义化版本和依赖描述中,通常使用范围约束,允许兼容更新。
^1.2.3:允许>=1.2.3且<2.0.0(即主版本不变)。~1.2.3:允许>=1.2.3且<1.3.0(即只允许修订号更新)。>=1.2.3 <2.0.0:更加精确地允许主版本不变的任何次版本和修订号更新。
- 重要:如果你的项目作为库被他人使用,描述你的依赖关系时,尽量明确兼容范围,避免锁定精确版本,这有助于下游用户解决依赖冲突。
- 在语义化版本和依赖描述中,通常使用范围约束,允许兼容更新。
常见误区与最佳实践
- 误区:认为大版本号只代表大重写。任何不兼容的改动,即使非常小(例如只改了函数参数类型),都需要递增主版本号。
- 误区:认为
x.y不需要 SemVer。需要。x.y遵循相同规则,但主版本号为 0 阶段 API 不稳定,你可以随时做不兼容修改并递增次版本号(1.0->2.0视为不兼容)。 - 最佳实践:
- 在发布前仔细检查是否增加了新功能、修复了 bug、做了不兼容更改。
- 在 CHANGELOG 中记录变更,说明每个版本的变化,并注明每个变化是新增、修复还是破坏性变更,这有助于用户了解升级的影响。
- 使用自动化工具:许多语言(如 Rust 的
cargo semver-checks,Go 的gorelease,Node.js 的semantic-release等)可以自动检查 API 变化并建议正确的版本号。 - 谨慎对待“废弃”功能:用次版本号标记废弃,但不要立刻删除,在下一个主版本中才最终移除,给用户留出迁移时间。
| 版本号组成部分 | 何时增加 | 对用户的影响 |
|---|---|---|
| 主版本 (MAJOR) | 不兼容的 API 修改 | 需要修改代码 |
| 次版本 (MINOR) | 向后兼容的新功能 | 可安全升级,新功能可用 |
| 修订号 (PATCH) | 向后兼容的 Bug 修复 | 可安全升级,无新功能 |
遵循语义化版本的核心是诚实、明确地传达你的改动对下游用户的影响,它让用户能放心地更新依赖,从而推动整个开源生态的健康协作。