
理解 Bumpversion 的版本部分处理机制
Bumpversion 是一个强大的版本管理工具,它通过解析(parse)当前版本字符串,识别出不同的版本部分(如 major, minor, patch, dev, build 等),然后根据用户指令递增或修改特定部分,最后再将这些部分序列化(serialize)成新的版本字符串。
在 bumpversion 的配置中,我们可以为每个版本部分定义一个 values 列表,指定该部分可能包含的所有合法值。当 bumpversion 尝试递增某个部分时,它会在该部分的 values 列表中查找当前值,并尝试将其替换为列表中的下一个值。
然而,当一个版本部分(例如 dev)的 values 列表中只包含一个值时,bumpversion 会将其视为已达到该部分的“最大值”。在这种情况下,如果你尝试对该部分执行 bump 操作,bumpversion 会抛出 ValueError: The part has already the maximum value... 错误,因为它认为没有下一个值可以递增。这对于实现“可选”的 dev 版本后缀(即有时需要 dev 后缀,有时不需要)构成了挑战。
解决方案:引入空值作为初始状态
为了实现可选的 dev 版本后缀,我们需要“欺骗” bumpversion,使其认为 dev 部分在未指定时也有一个“前一个”状态。最简单有效的方法是,在 [bumpversion:part:dev] 配置的 values 列表中,将第一个元素设置为空字符串 ""。
示例配置:
[bumpversion] current_version = 1.5.3 parse = (?P\d+)\.(?P \d+)\.(?P \d+)(-(?P .*)-(?P \d+))? serialize = {major}.{minor}.{patch}-{dev}-{build} {major}.{minor}.{patch} [bumpversion:part:dev] values = "" dev [bumpversion:part:build] first_value = 1
配置解析:
-
[bumpversion] 部分:
- current_version: 应用程序的当前版本。
- parse: 这是一个正则表达式,用于解析版本字符串。
- (?P
\d+)\.(?P \d+)\.(?P \d+):匹配主、次、补丁版本号。 - (-(?P
.*)-(?P \d+))?:这是一个关键部分。 - ? 使整个 (-(?P
.*)-(?P \d+)) 部分成为可选的。这意味着 bumpversion 可以匹配 1.5.3 这样的版本,也可以匹配 1.5.3-dev-1 这样的版本。 - (?P
.*):捕获 dev 部分的任意字符。 - (?P
\d+):捕获 build 部分的数字。
- ? 使整个 (-(?P
- (?P
- serialize: 定义了如何将解析出的版本部分重新组合成字符串。
- {major}.{minor}.{patch}-{dev}-{build}:用于生成带 dev 和 build 后缀的版本。
- {major}.{minor}.{patch}:用于生成不带后缀的标准版本。bumpversion 会尝试匹配最长的序列化格式,如果 dev 和 build 部分为空,则会匹配第二个格式。
-
[bumpversion:part:dev] 部分:
- values = ""\n dev:这是核心改动。通过将 "" 作为 dev 部分的第一个值,bumpversion 在初始状态(即版本号不带 dev 后缀时,dev 部分被解析为空字符串)下,会认为 dev 部分当前处于 "" 状态,并且存在一个可递增的下一个状态 dev。
-
[bumpversion:part:build] 部分:
dmSOBC SHOP网店系统下载dmSOBC SHOP网店系统由北京时代胜腾信息技术有限公司(http://www.webzhan.com)历时6个月开发完成,本着简单实用的理念,商城在功能上摒弃了外在装饰的一些辅助功能,尽可能的精简各项模块开发,做到有用的才开发,网店V1.0.0版本开发完成后得到了很多用户的使用并获得了好评,公司立即对网店进行升级,其中包括修正客户提出的一些意见和建议,现对广大用户提供免费试用版本,如您在使用
- first_value = 1:定义 build 部分的起始值。
工作原理深入解析
当 current_version 为 1.5.3 时:
- bumpversion 使用 parse 正则表达式解析 1.5.3。由于 (-(?P
.*)-(?P \d+))? 部分是可选的,dev 和 build 部分会被解析为空。 - 此时,dev 部分的内部状态被认为是 ""。
- 当你执行 bumpversion dev 命令时,bumpversion 会查找 [bumpversion:part:dev] 配置中的 values 列表。它发现 "" 是列表中的第一个值,并且 dev 是下一个值。
- 因此,bumpversion 可以成功地将 dev 部分从 "" 递增到 dev,同时将 build 部分初始化为 first_value(即 1)。
- 最终生成 1.5.3-dev-1 这样的版本号。
重要提示: bumpversion 的版本递增通常是非循环的。这意味着一旦 dev 部分从 "" 变为 dev,你无法通过 bumpversion dev 命令再将其变回 ""。要回到标准版本,你需要手动编辑 current_version 或使用其他 bumpversion 命令(如 bumpversion patch 等),这些命令在序列化时会选择不包含 dev 和 build 的格式。
实际操作示例
假设 bumpversion.cfg 按照上述配置:
-
初始状态: current_version = 1.5.3
- 执行 bumpversion dev
- 结果:current_version = 1.5.3-dev-1 (或 1.5.3-dev-1 如果 build 部分被 bump 到 1)
-
在开发版本上递增构建号: current_version = 1.5.3-dev-1
- 执行 bumpversion build
- 结果:current_version = 1.5.3-dev-2
-
在开发版本上递增补丁号(会重置 dev 和 build): current_version = 1.5.3-dev-2
- 执行 bumpversion patch
- 结果:current_version = 1.5.4 (注意 dev 和 build 部分被移除,因为它们不是 patch 的子部分,并且在序列化时,不带 dev 和 build 的格式被选择)
-
再次进入开发版本: current_version = 1.5.4
- 执行 bumpversion dev
- 结果:current_version = 1.5.4-dev-1
注意事项
- 正则表达式的精确性: 确保 parse 正则表达式能够正确匹配你期望的所有版本格式,特别是可选部分的括号和问号。
- 序列化顺序: serialize 列表的顺序很重要。bumpversion 会尝试匹配第一个能完全填充所有捕获组的序列化格式。如果 dev 和 build 部分为空,它会回退到不包含它们的序列化格式。
- 非循环性: 明确此方法主要是为了从无 dev 后缀状态“进入” dev 后缀状态。要从 dev 后缀状态“退出”到无后缀状态,通常需要通过递增更高级别的版本部分(如 patch、minor、major),或者手动修改 current_version。
- first_value 的使用: first_value 属性对于像 build 这样的数字递增部分非常有用,它定义了该部分在首次出现时的起始值。
通过上述配置和理解,您可以灵活地使用 Bumpversion 管理带有可选开发版本后缀的项目版本,从而更好地适应不同的发布和开发流程。









