包版本控制

始终引用特定包的包标识符和确切版本号。 例如,nuget.org 上的 实体框架 有几十个可用的特定包,从版本 4.1.10311 到版本 6.1.3(最新稳定版本)和各种预发行版本(如 6.2.0-beta1)。

创建包时,可以使用可选的预发行文本后缀分配特定的版本号。 另一方面,使用包时,可以指定确切的版本号或可接受的版本范围。

以下文档遵循 NuGet 4.3.0+ 和 Visual Studio 2017 版本 15.3+ 支持的 语义版本控制 2.0.0 标准。 旧版客户端不支持 SemVer v2.0.0 的某些 语义。

在本主题中:

版本基础知识

特定版本号采用 Major.Minor.Patch[-Suffix]的形式,其中组件具有以下含义:

  • 主要:重大更改
  • 次要:新功能,但向后兼容
  • 修补程序:仅向后兼容的 bug 修复
  • -Suffix(可选):一个连字符,后跟一个表示预发行版本的字符串(遵循 语义版本控制或 SemVer 约定)。

示例:

1.0.1
6.11.1231
4.3.1-rc
2.2.44-beta.1

重要

nuget.org 拒绝缺少确切版本号的任何包上传。 必须在用于创建包的 .nuspec 或项目文件中指定版本。

预发行版本

从技术上讲,包创建者可以使用任何字符串作为后缀来表示预发行版本,因为 NuGet 将任何此类版本视为预发行版本,并且不会做出其他解释。 也就是说,NuGet 在涉及的任何 UI 中显示完整版本字符串,从而将后缀的含义的任何解释留给使用者。

也就是说,包开发人员通常遵循公认的命名约定:

  • -alpha:Alpha 版本,通常用于正在进行的和试验。
  • -beta:Beta 版本,通常是下一个计划版本中的功能完成版本,但可能包含已知的 bug。
  • -rc:候选发布,通常是潜在的最终版本(稳定),除非出现重大 bug。

按优先顺序对版本进行排序时,NuGet 遵循 SemVer 标准,先选择不带后缀的版本,然后按反向字母顺序对预发布版本应用优先级,并使用数字顺序处理点表示法数字。

注意

带点表示法的预发行版数字(如 1.0.1-build.23)被视为 SemVer 2.0.0 标准的一部分,因此,nuGet 4.3.0+仅支持

1.0.1
1.0.1-zzz
1.0.1-rc.10
1.0.1-rc.2
1.0.1-open
1.0.1-beta
1.0.1-alpha2
1.0.1-alpha10
1.0.1-aaa

请注意,1.0.1-alpha10 严格按反向字母顺序排序,而 1.0.1-rc.10 的优先级高于 1.0.1-rc.2。

版本范围

引用包依赖项时,NuGet 支持使用间隔表示法来指定版本范围,如下所示:

表示法 已应用规则 描述
1.0 x ≥ 1.0 最低版本(非独占)
[1.0,) x ≥ 1.0 最低版本(非独占)
(1.0,) x > 1.0 最低版本,独占
[1.0] x == 1.0 确切的版本匹配
(,1.0] x ≤ 1.0 最大版本(非独占)
(,1.0) x < 1.0 最大版本,独占
[1.0,2.0] 1.0 ≤ x ≤ 2.0 精确范围(含)
(1.0,2.0) 1.0 < x < 2.0 精确范围,独占
[1.0,2.0) 1.0 ≤ x < 2.0 混合非独占最低版本和独占最大版本
(1.0) 无效 无效

最佳做法

始终为项目文件中的包依赖项、packages.config 文件和 .nuspec 文件指定版本或版本范围。 如果没有版本或版本范围,在解析依赖项时,不能保证一致的还原结果。 除非知道兼容性问题,否则请避免将版本范围的上限指定到你不拥有的包。 对版本范围的上限会损害采用,阻止使用者获取对依赖项的宝贵更新,在某些情况下可能会导致用户使用不受支持的依赖项版本。

项目文件中的引用 (PackageReference)

<!-- Accepts any version 6.1 and above.
     Will resolve to the smallest acceptable stable version.-->
<PackageReference Include="ExamplePackage" Version="6.1" />

<!-- Accepts any 6.x.y version.
     Will resolve to the highest acceptable stable version.-->
<PackageReference Include="ExamplePackage" Version="6.*" />

<!-- Accepts any version above, but not including 4.1.3. Could be
     used to guarantee a dependency with a specific bug fix. 
     Will resolve to the smallest acceptable stable version.-->
<PackageReference Include="ExamplePackage" Version="(4.1.3,)" />

<!-- Accepts any version up below 5.x, which might be used to prevent pulling in a later
     version of a dependency that changed its interface. However, this form is not
     recommended because it can be difficult to determine the lowest version. 
     Will resolve to the smallest acceptable stable version.
     -->
<PackageReference Include="ExamplePackage" Version="(,5.0)" />

<!-- Accepts any 1.x or 2.x version, but not 0.x or 3.x and higher.
     Will resolve to the smallest acceptable stable version.-->
<PackageReference Include="ExamplePackage" Version="[1,3)" />

<!-- Accepts 1.3.2 up to 1.4.x, but not 1.5 and higher.
     Will resolve to the smallest acceptable stable version. -->
<PackageReference Include="ExamplePackage" Version="[1.3.2,1.5)" />

packages.config中的 引用:

packages.config中,每个依赖项都会列出,其中包含还原包时使用的确切 version 属性。 allowedVersions 属性仅在更新操作期间使用,以限制包可能更新到的版本。

<!-- Install/restore version 6.1.0, accept any version 6.1.0 and above on update. -->
<package id="ExamplePackage" version="6.1.0" allowedVersions="6.1.0" />

<!-- Install/restore version 6.1.0, and do not change during update. -->
<package id="ExamplePackage" version="6.1.0" allowedVersions="[6.1.0]" />

<!-- Install/restore version 6.1.0, accept any 6.x version during update. -->
<package id="ExamplePackage" version="6.1.0" allowedVersions="[6,7)" />

<!-- Install/restore version 4.1.4, accept any version above, but not including, 4.1.3.
     Could be used to guarantee a dependency with a specific bug fix. -->
<package id="ExamplePackage" version="4.1.4" allowedVersions="(4.1.3,)" />

<!-- Install/restore version 3.1.2, accept any version up below 5.x on update, which might be
     used to prevent pulling in a later version of a dependency that changed its interface.
     However, this form is not recommended because it can be difficult to determine the lowest version. -->
<package id="ExamplePackage" version="3.1.2" allowedVersions="(,5.0)" />

<!-- Install/restore version 1.1.4, accept any 1.x or 2.x version on update, but not
     0.x or 3.x and higher. -->
<package id="ExamplePackage" version="1.1.4" allowedVersions="[1,3)" />

<!-- Install/restore version 1.3.5, accepts 1.3.2 up to 1.4.x on update, but not 1.5 and higher. -->
<package id="ExamplePackage" version="1.3.5" allowedVersions="[1.3.2,1.5)" />

.nuspec 文件中 引用

<dependency> 元素中的 version 属性描述依赖项可接受的范围版本。

<!-- Accepts any version 6.1 and above. -->
<dependency id="ExamplePackage" version="6.1" />

<!-- Accepts any version above, but not including 4.1.3. Could be
     used to guarantee a dependency with a specific bug fix. -->
<dependency id="ExamplePackage" version="(4.1.3,)" />

<!-- Accepts any version up below 5.x, which might be used to prevent pulling in a later
     version of a dependency that changed its interface. However, this form is not
     recommended because it can be difficult to determine the lowest version. -->
<dependency id="ExamplePackage" version="(,5.0)" />

<!-- Accepts any 1.x or 2.x version, but not 0.x or 3.x and higher. -->
<dependency id="ExamplePackage" version="[1,3)" />

<!-- Accepts 1.3.2 up to 1.4.x, but not 1.5 and higher. -->
<dependency id="ExamplePackage" version="[1.3.2,1.5)" />

规范化版本号

注意

这是 NuGet 3.4+ 的重大更改。

在安装、重新安装或还原操作期间从存储库获取包时,NuGet 3.4+ 将版本号视为如下所示:

  • 从版本号中删除前导零:

    • 1.00 被视为 1.0
    • 1.01.1 被视为 1.1.1
    • 1.00.0.1 被视为 1.0.0.1
  • 将省略版本号第四部分中的零

    • 1.0.0.0 被视为 1.0.0
    • 1.0.01.0 被视为 1.0.1
  • 删除 SemVer 2.0.0 生成元数据

    • 1.0.7+r3456 被视为 1.0.7

packrestore 操作尽可能规范化版本。 对于已生成的包,此规范化不会影响包本身的版本号;它仅影响 NuGet 在解析依赖项时与版本匹配的方式。

但是,NuGet 包存储库必须以与 NuGet 相同的方式对待这些值,以防止包版本重复。 因此,包含包版本 1.0 的存储库不应将版本 1.0.0 作为单独的包承载。

语义版本控制 2.0.0

旧客户端不支持 SemVer v2.0.0 的某些语义。 如果以下任一语句为 true,NuGet 会将包版本视为特定于 SemVer v2.0.0:

  • 预发行标签是点分隔的,例如,1.0.0-alpha.1
  • 版本具有生成元数据,例如,1.0.0+githash

对于 nuget.org,如果以下任一语句为 true,则包定义为 SemVer v2.0.0 包:

  • 包自己的版本符合 SemVer v2.0.0,但不符合上述定义的 SemVer v1.0.0。
  • 任何包的依赖项版本范围都具有最低或最大版本,该版本符合 SemVer v2.0.0,但不符合 SemVer v1.0.0 标准,上面定义:例如,[1.0.0-alpha.1, )

如果将 SemVer v2.0.0 特定包上传到 nuget.org,则包对较旧的客户端不可见,并且仅适用于以下 NuGet 客户端:

  • NuGet 4.3.0+
  • Visual Studio 2017 版本 15.3+
  • Visual Studio 2015 与 NuGet VSIX v3.6.0
  • .NET SDK 2.0.0+

第三方客户端:

  • JetBrains Rider
  • Paket 版本 5.0+

NuGetVersion 与语义版本控制存在分歧的位置

如果要以编程方式使用 NuGet 包版本,强烈建议 包 NuGet.Versioning。 静态方法 NuGetVersion.Parse(string) 可用于分析版本字符串,VersionComparer 可用于对 NuGetVersion 实例进行排序。

如果要以不在 .NET 上运行的语言实现 NuGet 功能,以下是 NuGetVersion 与语义版本控制之间的差异的已知列表,以及现有语义版本控制库可能不适用于已在 nuget.org 发布的包的原因。

  1. NuGetVersion 支持第四个版本段(Revision)与 System.Version的超集兼容。 因此,不包括预发行版和元数据标签,版本字符串 Major.Minor.Patch.Revision。 根据上述版本规范化,如果 Revision 为零,则会从规范化版本字符串中省略它。
  2. NuGetVersion 只需要定义主要段。 所有其他项都是可选的,等效于零。 这意味着,11.01.0.01.0.0.0 都接受和平等。
  3. NuGetVersion 对预发行组件使用不区分大小写的字符串比较。 这意味着 1.0.0-alpha1.0.0-Alpha 相等。