Skip to content

在现代软件开发中,依赖管理是一个核心挑战。为了在复杂的依赖关系中清晰地传达变更的性质与风险,业界形成了一套广泛采纳的规范 —— 语义化版本控制(Semantic Versioning, SemVer)。它不仅是一种版本编号方案,更是一种开发者之间的沟通契约。遵循 SemVer 规范,能极大地提升软件生态的稳定性和可预测性。

本文将快速解析 SemVer 2.0.0 的核心规则。

1. 基石:公共 API 的定义

任何采用 SemVer 的软件,必须声明一个公共 API(Public API)。这个 API 是软件与外部世界交互的契约,其稳定性是版本控制的依据。

  • 形式: API 可以通过代码本身(例如,公共类、方法、模块导出)明确定义,也可以在严谨、详尽的文档中进行阐述。
  • 要求: 无论形式如何,API 的定义都必须精确且完整,以便使用者能够清晰地理解其功能、参数和行为。

2. 版本号结构

标准的版本号必须采用 X.Y.Z 的格式,它由三个非负整数部分组成:

  • X: 主版本号 (Major)
  • Y: 次版本号 (Minor)
  • Z: 修订号 (Patch)

格式要求:

  • 各部分数值以点(.)分隔。
  • 禁止在数字前方补零(例如,1.01.2 是无效的)。
  • 版本号的递增是基于数值的,而非字符串。例如:1.9.0 -> 1.10.0 -> 1.11.0

3. 版本更新的核心准则

版本号的更新直接反映了其底层代码变更的性质。

初始开发阶段:0.y.z

主版本号为 0 的版本(如 0.1.0, 0.2.5)被视为初始开发阶段。在此阶段,公共 API 尚不稳定,可能随时发生不兼容的变更。因此,不应将其用于生产环境或视为稳定的依赖。

正式发布:1.0.0

1.0.0 版本的发布是一个重要的里程碑,它标志着稳定的公共 API 的诞生。从这个版本开始,所有的版本号更新都必须严格依据公共 API 的变更来执行。

版本递增规则 (当 X > 0):

  • 修订号 (Z) 的递增: 当且仅当进行了**向后兼容的错误修复 (backwards-compatible bug fixes)**时,才递增修订号。例如,修复了一个导致不正确输出的内部缺陷。

    • x.y.Z -> x.y.(Z+1)
  • 次版本号 (Y) 的递增: 当引入了**向后兼容的新功能 (backwards-compatible new functionality)时,递增次版本号。此外,当任何公共 API 的部分被标记为弃用 (deprecated)**时,也必须递增次版本号。此级别的更新可以包含修订级别的变更。递增次版本号时,修订号必须归零

    • x.Y.z -> x.(Y+1).0
  • 主版本号 (X) 的递增: 当发生任何**不兼容的 API 变更 (incompatible API changes)**时,必须递增主版本号。这包括移除、重命名或修改现有 API 的签名。此级别的更新可以包含次版本和修订级别的变更。递增主版本号时,次版本号和修订号都必须归零

    • X.y.z -> (X+1).0.0

4. 扩展标识符

为了标记预发布版本或附加构建信息,SemVer 允许在核心版本号后添加扩展标识符。

先行版本号 (Pre-release Version)

用于标记不稳定的预发布版本,如 alpha, beta, rc

  • 格式: 在修订号后附加一个连字符(-)和一系列点分隔的标识符。
  • 标识符: 仅允许使用 ASCII 字母数字和连字符 [0-9A-Za-z-]。数字标识符禁止前导零。
  • 优先级: 先行版本的优先级低于其关联的常规版本。例如,1.0.0-rc.1 的优先级低于 1.0.0
  • 示例: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92

版本编译信息 (Build Metadata)

用于附加构建过程中的元数据,如编译时间戳、Git-hash 等。

  • 格式: 在修订号或先行版本号后附加一个加号(+)和一系列点分隔的标识符。
  • 标识符: 规则与先行版本号相同。
  • 优先级: 在进行版本优先级比较时,必须忽略版本编译信息。因此,仅编译信息不同的两个版本(如 1.0.0+202301011.0.0+20230102)优先级相同。
  • 示例: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85

5. 版本的不可变性

这是一个基础但至关重要的原则:一旦一个版本被发布,其内容便不可变更。任何后续的修改都必须作为新版本重新发布。这保证了版本号的引用是确定和可靠的。

6. 优先级与比较规则

版本的优先级决定了其在依赖解析和排序中的顺序。比较规则如下:

  1. 比较顺序: 依次比较 主版本号次版本号修订号。这三者都按数值大小进行比较。

    • 示例: 1.0.0 < 2.0.0 < 2.1.0 < 2.1.1
  2. 先行版本的介入: 当主、次、修订号均相同时,拥有先行版本号的版本优先级更低

    • 示例: 1.0.0-alpha < 1.0.0
  3. 先行版本间的比较: 若两个版本的主、次、修订号相同,则需逐个比较由点分隔的先行版本标识符:

    • 数字标识符按数值比较。
    • 字母或混合标识符按 ASCII 字典序比较。
    • 数字标识符的优先级低于非数字标识符
    • 当比较到某处时,若一个版本的标识符字段更多,则其优先级更高。
    • 综合示例: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0

SemVer 规范为软件版本管理提供了一套清晰、通用且富有表达力的语言。它通过严格的规则,将版本号与软件的 API 变更直接挂钩,从而使开发者能够安全、高效地管理项目依赖,避免了“依赖地狱”的困境。准确理解并应用 SemVer,是每一位专业软件工程师必备的技能。