探索语义化版本控制

已完成

版本控制的主要方式之一是使用 语义版本控制 (SemVer)。

语义版本控制 不是标准,但提供一致的方式来表达特定版本的 意向语义

它描述了一个特性,该特性使其能够与以前的版本向后兼容

语义化版本格式

语义版本控制 使用 由三部分构成的版本号 和可选 标签

Major.Minor.Patch 格式

版本采用 Major.Minor.Patch 的形式,对应于上一部分介绍的三种类型的更改。

版本结构:

  • 主要: 第一个数字,指示重大变更。
  • 次要: 第二个数字,指示新功能(向后兼容)。
  • 补丁: 第三个数字,指示 bug 修复(向后兼容)。

使用语义版本控制方案的版本示例:

  • 1.0.0 - 初始稳定版本
  • 3.7.129 - 版本 3 包含许多次要和补丁更新
  • 2.0.0 - 具有重大更改的主要版本 2

这些版本没有任何标签。

版本增量规则

何时递增每个数字:

主要版本递增 (X.0.0)

  • 重大变更: 进行 API 不兼容更改。
  • 删除功能: 删除已弃用的功能。
  • 体系结构更改: 基本重新设计。

Example:

  • 1.5.3在引入重大变更时→2.0.0

次要版本递增(x.Y.0)

  • 新功能: 以向后兼容的方式添加功能。
  • 弃用功能: 将功能标记为已弃用(但仍正常运行)。
  • 增强: 对现有功能的大幅改进。

Example:

  • 在添加新功能时,将1.5.3转变为1.6.0

修补程序递增(x.y.Z)

  • Bug 修复: 进行向后兼容的 bug 修复。
  • 安全修补程序: 修复安全漏洞。
  • 性能改进: 轻微的性能优化。

Example:

  • 1.5.31.5.4用于 bug 修复

预发行版版本

对于 预发行版本,通常使用常规版本号后的 标签

标签格式

标签是文本后缀,用连字符与版本号的其余部分分隔。

标签本身可以是描述 预发行版性质的任何文本。

标签结构:

Major.Minor.Patch-label

常见的预发行版标签

这些示例包括 rc1beta27以及 alpha形成版本号,例如:

  • 1.0.0-alpha - 早期开发版本,不稳定。
  • 1.0.0-beta - 功能已完成,但可能存在 bug。
  • 1.0.0-beta.2 - 第二个 beta 版本。
  • 1.0.0-rc1 - 发行候选版,有可能准备就绪以供发布。
  • 1.0.0-preview - 用于早期反馈的预览版本。

版本进度示例:

1.0.0-alpha.1
1.0.0-alpha.2
1.0.0-beta.1
1.0.0-beta.2
1.0.0-rc1
1.0.0-rc2
1.0.0

预发布标签约定

常见标签前缀:

  • alpha:非常早期的版本,可能会有 bug 和重大变更。
  • 试用版: 功能完成,正在进行测试。
  • rc(发行候选版): 可能是最终版本,属于最后一个测试阶段。
  • 预览: 用于反馈的早期预览。
  • dev:开发快照。

数字后缀:

标签通常包括用于预发布版本的顺序号:

  • 1.0.0-beta.1 1.0.0-beta.2 →→1.0.0-beta.3

使用预发行版版本

预发布 是准备发布包的无标签版本的常见方法。

预发布的好处

早期反馈:

早期采用者 可以依赖预发行版来利用新包进行构建。

  • 测试集成: 验证包是否适用于现有系统。
  • 报告问题: 在正式发布之前发现错误。
  • 提供反馈: 建议改进或更改。

逐步推出:

  • 分阶段发布: 首先向小型受众发布。
  • 风险缓解: 在广泛发布之前发现问题。
  • 置信度构建: 建立对稳定性的信心。

预发行注意事项

通常, 使用预发行版本的包及其组件进行发布的软件并不是一个好主意

在生产中使用预发布的风险:

  • 不稳定: 预发布版本可能存在未发现的漏洞。
  • 重大变更: 未来的预发布可能会引入重大变更。
  • 不保证: 没有向后兼容性保证。
  • 支持限制: 对预发行版版本有限或不支持。

测试预发行版版本

最好是在代码库中创建单独的分支并使用包的预发行版本来期待新组件的影响。

用于测试预发布项的最佳做法:

  • 单独的分支: 创建用于测试的功能分支。
  • 独立环境: 在非生产环境中进行测试。
  • 观察行为: 注意异常行为或性能问题。
  • 文档问题: 跟踪发现的任何问题。

很有可能会有从预发行版到最终版本的不兼容更改。

元数据和生成信息

SemVer 2.0 还支持使用加号附加的构建元数据

1.0.0-beta.1+20231015.abc123

生成元数据:

  • 在版本优先级中不考虑: 仅在生成元数据中不同两个版本被视为相等。
  • 信息用途:可用于跟踪内部版本号、提交哈希。
  • 例:1.0.0+build.1231.0.0-beta+exp.sha.5114f85

版本优先级

SemVer 为版本优先级定义明确的规则:

比较规则

  1. 比较主要版本,次要版本,修补程序:按数字顺序。
  2. 预发行版版本: 优先级始终低于关联的正常版本。
  3. 标签比较: 字母数字段按字典顺序比较,数值段按数值比较。

按顺序排列的示例(最低到最高):

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
1.0.1
1.1.0
2.0.0

语义化版本管理的优势

清晰沟通:

  • 意图: 版本号清楚地传达更改的性质。
  • 兼容性: 易于确定更新是否安全。
  • 可 预见性: 跨包进行一致的版本控制。

自动依赖项管理:

  • 版本约束: 包管理器可以自动解析版本。
  • 安全更新: 工具可以安全地更新到兼容版本。
  • 冲突解决: 更轻松地解决依赖项冲突。

生态系统采纳:

  • 行业标准: 在许多生态系统中广泛采用。
  • 工具支持: 包管理器了解 SemVer。
  • 社区期望: 开发人员需要 SemVer 符合性。

Azure Artifacts 中的语义版本控制

Azure Artifacts 支持跨所有包类型的 语义版本控制

  • NuGet: 原生 SemVer 2.0 支持。
  • npm: SemVer 是标准。
  • Maven: 与 SemVer 原则兼容。
  • Python: PEP 440 与 SemVer 概念兼容。
  • 通用包: 使用 SemVer 2.0。

源视图和 SemVer:

  • @Prerelease 视图:自动包含带有标签的版本。
  • @Release视图: 仅包含未加标签的版本。
  • @Local视图: 显示所有版本,不考虑标签。

实现语义版本控制

手动版本控制:

  • 更新包文件:package.json.nuspec等中手动更新版本
  • 带有标签的提交: 用版本号给提交打标签。

自动版本控制:

# Using npm version command
npm version patch  # Increment patch: 1.0.0 -> 1.0.1
npm version minor  # Increment minor: 1.0.1 -> 1.1.0
npm version major  # Increment major: 1.1.0 -> 2.0.0

# With prerelease
npm version prerelease --preid=beta  # 1.0.0 -> 1.0.1-beta.0

在 CI/CD 管道中:

# Azure Pipelines example
- task: GitVersion@5
  inputs:
    runtime: "core"
    configFilePath: "GitVersion.yml"

- script: |
    echo "Semantic Version: $(GitVersion.SemVer)"
    echo "NuGet Version: $(GitVersion.NuGetVersion)"
  displayName: "Display version"

另请参阅 语义版本控制 2.0.0