命名有意义的版本号2.0.0

原文链接:http://semver.org/

翻译:yaoxing、石硕

校验:周迁勇

摘要

给定一个版本号 主要版本号.次要版本号.补丁版本号,按照下面的规则更新:

1.增加主要版本号,当API不再向下兼容时

2.增加次要版本号,当API以向下兼容的方式增加新功能时

3.增加补丁版本号,当API以向下兼容的方式修复BUG时

预览版本号和构建版本号可以以扩展的方式添加到主要版本号.次要版本号.补丁版本号后面。

简介

在软件管理的世界里有一个可怕的地方叫“依赖地狱(dependency hell)”。你的系统越是成长壮大,你越是整合更多的软件包到你自己的系统中,你越有可能在将来的某天发现自己已经掉进了这个绝望的深渊。

在一个有着众多依赖的系统里,发布新版本可能很快成为一个恶梦。如果依赖定义得过于紧密,你就有可能进入版本锁定(version lock)的状态(版本锁定是指一旦更新一个软件包,就不得不更新其他所有依赖于它的包)。如果依赖定义得过于松散,你又难免会被版本穿插(version promiscuity)所伤(让人以为会与多得不合理的未来版本兼容)。当你被版本锁定或版本穿插所阻挠而不能容易地让你的项目顺利前进时,你就身处依赖地狱中了。

作为这个问题的解决方案之一,我提议用一组简单的规则和要求来约束版本号的分配和增长规则。为了让这套理论运作,你必须预先定义好自己的公共API。这可以通过文档定义或代码强制要求来实现。无论如何,这套API的清楚明了是十分重要的。一旦你定义了公共API,你就可以通过修改相应的版本号来通知大家你的修改。考虑使用这样的版本号格式:X.Y.Z(主版本号,次版本号,补丁版本号)修复Bug但不影响API时增长补丁版本号;API保持向下兼容的增加/修改时增长次版本号;进行不向下兼容的修改时增长主版本号。

我把这套规则称为“语义版本命名(Semantic Versioning)”。在这套工作模式下,版本号和它们的增长模式就会传达从当前版本向下一个版本进行了怎样的修改。

语义版本(SemVer)命名规范

在篇文章里出现的关键字必须”,“必须不”,“要求”,“应该”,“不应该”,“一定要”,“一定不要”,“推荐”,“可以”和“可选将在RFC2119中描述和解释。(以下译文中原样使用这些关键字看上去会比较生硬,但为了清楚地传达作者的意图和保持RFC2119关键字的意义,仍然照这里的翻译来使用——译者注)

  1. 使用语义版本命名的软件系统必须定义一套公共API。这套API可以是在代码中申明或是用严格的文档定义。不管怎样做,它都应该清楚明了。
  2. 正常的版本号必须使用X.Y.Z的形式并且X/Y/Z是非负整数,并且必须不能以零作为前导。X是主版本号,Y是次版本号,Z是补丁版本号。版本号每次必须只能增长1。例如:1.9.0->1.10.0->1.11.0。
  3. 一旦发布了具有版本的包,那个版本的内容必须不能再更改。任何修改必须发布成一个新版本。
  4. 主版本号0 (0.y.z)是用来进行初始开发时使用的。任何东西都可能在任何时候改变。公共API此时应该被认为是经常变动的。
  5. 版本1.0.0开始定义公共API。这个版本及以后的版本号的增长方式将依赖于公共API以及它如何变化。
  6. 如果有任何向下兼容的bug修复发生,补丁版本号Z (x.y.Z | x > 0)必须增长1。“bug修复”被定义为内部进行的修复非正常行为的修复工作。
  7. 如果进行了新的并且向下兼容的公共API添加和修改,次版本号Y (x.Y.z | x > 0)必须增长1。如果任何公共API被标记为“过期”,次版本号必须增长1;如果有大量的新功能或改进在内部代码中发生,次版本号可以增长1;这其中也可以包含补丁级别的修改。当次版本号增长时补丁版本号必须清零。
  8. 如果对公共API有任何向下不兼容的修改,主版本号X (X.y.z | X > 0)必须增长1。这其中也可以包含次版本和补丁版本级别的修改。当主版本号增长时次版本号和补丁版本号必须清零。
  9. 预览版本(pre-release version)可以通过在补丁版本号后追加中横线以及由点分隔开的一系列标识来表达。标识必须由ASCII字符和中横线[0-9A-Za-z-]组成。预览版本能满足相关版本的要求,但优先级低于相关版本。例如:1.0.0-alpha,1.0.0-alpha.2,1.0.0-0.3.7,1.0.0-x.7.z.92。
  10. 构建版本(build version)可以通过在补丁版本号或预览版本后追加一个加号和一系列由点分隔标识来表达。标识必须由ASCII字符和中横线[0-9A-Za-z-]组成。构建版本能够满足相关版本的要求,并且优先于相关版本。例如:1.0.0+build.1,1.3.7+build.11.e0f985a。
  11. 将版本号分为主版本号、次版本号、补丁版本号,预览版本,构建版本,必须按这样的按顺序分别逐级考虑来确定版本顺序。主版本号、次版本号,补丁版本号总是通过数字大小来确定顺序。预览版本和构建版本的顺序必须由比较由点分隔标识来确定,规则如下:如果标识只有数字,则由数字大小决定;如果标识包含字符和中横线,则由比较字符的字典顺序来确定。数字标识的顺序永远低于非数字标识。例如:1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0-rc.1+build.1 < 1.0.0 < 1.0.0+0.3.7 < 1.3.7+build < 1.3.7+build.2.b8f12d7 < 1.3.7+build.11.e0f985a(注新版本的命名规范不如老版本中的示例全面,故此保留2.0.0-rc1中的示例)。

为什么使用语义版本命名?

这并不是一个全新的革命性的想法。事实上,你可能已经做了和这差不多的事情了。问题是“差不多”还不够好。如果不服从某种正式的规范,版本号对于版本依赖管理就失去了本质上的意义。通过给以上的想法一个清楚的定义和命名,与你的软件用户沟通你的意图就变得容易了。一旦这些意图明确表达出来,灵活(但不是过于灵活)的依赖定义就可以最终被制定出来。

一个简单的例子可以演示语义版本命名如何让版本地狱成为过去。考虑有一个库叫做“救火车”。它需要一个语义版本命名的包“云梯”。当救火车被制造的时候,云梯的版本是3.1.0。因为救火车一开始使用了由云梯3.1.0提供的某些功能,你可以安全地知道对云梯的正确依赖是在3.1.0以后并且4.0.0之前。现在,当云梯版本3.1.1和3.2.0发布时,你就可以把它们放到你的软件包管理系统中并且知道它们会与依赖它的软件兼容。

作为一个有责任的开发人员,你当然一定会想要确保所有软件包更新都被广而告之。现实世界是一个混乱的地方,除了提高警惕我们别无他法。你所能做的是让语义版本命名为你提供一个健全的方式来发布版本更新软件包,而不必更新所有的依赖软件包,这将会节省你的时间,少为你添麻烦。

如果这些听起来让你满意的话,你所需要对语义版本命名做的事情就是:申明你正在使用它并且按它的要求办事。在你的README文档中链接到这个网站,让其他人知道这些规则并且从中受益。

FAQ

  1. 在开发阶段,应该如何定义一个起始版本号?
    最简单的方法就是,以0.1.0版本作为起始,之后的更新增加次要版本号。
  2. 应该在何时发布1.0.0版本?
    如果你的软件已经准备使用在正式的发布产品中时,版本号应该更新为1.0.0.如果你的稳定API被其他用户作为依赖时,版本号应该更新为1.0.0.如果你已经开始担心很多的向下兼容性问题,版本号应该更新为1.0.0.
  3. 语义命名规范是否会阻碍快速开发和迭代开发?
    在快速开发阶段,主要版本号必须为零。如果你很频繁的修改API,版本号必须为0.x.y;如果增加次要版本号需要独立出一个新的分支。
  4. 如果任何一个很细小的向下兼容的改变都会导致主要版本号的臃肿,是否意味着我应该立即在42.0.0版本终止了呢?
    这是一个很负责任,而且很有远见的问题。不兼容的更改不应该被轻易的引入软件,特别是被其他项目依赖的代码。由此带来的的升级代价是昂贵的。当一个主要版本号十分臃肿时,这意味着,当你做任何修改时,需要考虑所花费的代价是否值得。
  5. 整理公共API文档太浪费时间了!
    作为一名专业开发者,你有责任为其他使用者提供软件开发文档。管理软件复杂性是保持项目效率的一个极其重要的部分,如果没有人知道如何使用这个软件,或者是如何安全的调用一个方法,这将会是一件很糟糕的事;从长远来看,使用语义版本命名规范定义公共API,可以让这个过程变得很自然。
  6. 如果我不小心发布了一个不向下兼容的次要版本时,该怎么办?
    如果你发现自己不小心破坏了语义版本命名规范,应当立即修复向下兼容的问题,并发布一个新的次要版本。即使在这种情况下,也是不允许修改版本号的。如果可以的话,在文档中注明该问题,并通知使用者。
  7. 如果我不小心更新了依赖,却忘记更新公共API时,该怎么办?
    如果更新不影响公共API,这将被认为是合理的。如果其他软件显式的引用你的包作为依赖项,那么每个软件应该有自己的单独的依赖性规范,这样,每个软件开发者将会注意到冲突。是更新补丁版本,还是次要版本,取决于你更新的依赖是修复BUG,还是增加新的功能。如果是更新次要版本,我通常会给出更新后版本的示例代码。
  8. 如果我无意中,以不符合版本命名规范的方式修改了公共API(例如:代码需要更新主要版本号,但是却只更新了补丁版本号),该怎么办?
    使用你最好的判断。如果你的软件有一个巨大的使用群体,并且修改的公共API极大的影响了他们,此时你最好发布一个新的主要版本,即使这次修复只是一个补丁。记住,语义命名规范是用来传达版本号变化的意义。如果这些变化对于你的使用者很重要,使用版本号来通知他们。
  9. 我应该如何处理一些微不足道的功能?
    微不足道的功能是软件开发过程中很常见的,这些功能需要改进。当你反对你的公共API时,你应该做两件事情:(1)更新你的文档来通知用户,你做了哪些更新,(2)发布一个新和次要版本。在你完全删除这个功能之前,至少应该发布一个新的次要版本,以此来通知用户,以此来帮助用户顺利的过渡到新版本。
  10. 语义版本命名规范对版本号长度是否有限制?
    没有,但是有一个建议。例如,一个255字符长度的版本号可能太长了。同时,不同的操作系统对客串的长度可能会有不同的限制。

 

关于

语义版本命名规范由Tom Preston-Werner提出,他是Gravatars的创始人和GitHub的合作创始人。

如果你想留下一些反馈,请在GitHub提交一个新的问题

License

Creative Commons – CC BY 3.0

参考

1.http://www.cnblogs.com/yaoxing/archive/2012/05/14/semantic-versioning.html

版权

版权所有:失乐园 | 杭州601号

文章链接:[译]命名有意义的版本号2.0.0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值