开发一个主版本更新

本文翻译自《Developing a major version update》。

目录

主版本更新的注意事项

为主版本的发布创建分支

当你在潜在的新版本中所做的更改不能保证模块用户的向后兼容性时,你必须把这些更改更新到主版本。例如,如果你更改模块的公开API会破坏使用该模块以前版本的客户端代码,你就应该通过开发一个新的主版本来实现这种更改。

注意:每个版本类型——主版本、次版本、补丁版本或预发布版本——对模块的用户来说都有不同的含义。这些用户依靠这些差异来了解版本对他们自己的代码所代表的风险级别。换句话说,在准备发布时,请确保其版本号准确地反映了自上一版本以来的更改的性质。有关版本号的更多信息,请参阅模块版本编号

另请参阅

主版本更新的注意事项

仅在绝对必要时才更新到新的主版本。因为主版本更新对你和你模块的用户来说都意味着重大的变化。当你考虑进行主版本更新时,请考虑以下事项:

  • 发布新的主版本对你以前的主版本的维护意味着什么,你需要向你的用户明确这一点。以前的版本是否已弃用?还是像以前一样支持?你会维护以前的版本,包括Bug修复吗?
  • 准备好维护两个版本:旧版本和新版本。例如,如果你修复了一个Bug,你通常会将这些修复移植到另一个中。
  • 请记住,从依赖管理的角度来看,新的主版本是一个新模块。在你发布新的主版本后,你的用户将需要更新以使用新模块,而不是简单地升级。这是因为新的主版本与之前的主版本具有不同的模块路径。例如,对于模块路径为example.com/mymodule的模块,v2版本将具有模块路径example.com/mymodule/v2。
  • 当你开发新的主版本时,你还必须在导入新模块里的包的那些代码里,修改导入路径。如果你的模块的用户想要升级到新的主版本,他们也必须更改他们的导入路径。

为主版本的发布创建分支

在准备开发新的主版本时,最直接的处理源代码的方式是从存储库创建先前主版本的最新版本的分支。

例如,在命令提示符下,你可以cd到模块的根目录,然后在那里创建一个新的v2分支。

$ cd mymodule
$ git checkout -b v2
Switched to a new branch "v2"

创建源代码的分支后,需要对新版本的源代码进行以下更改:

  • 在新版本的go.mod文件中,将新的主版本号附加到模块路径,如下例所示:

现有版本:example.com/mymodule

新版本:example.com/mymodule/v2

  • 在Go代码中,更新从该模块导入包的每个导入路径,将主版本号附加到模块路径部分。

旧的导入语句:import“example.com/mymodule/package1”

新的导入语句:import“example.com/mymodule/v2/package1”

有关发布步骤,请参见发布一个模块

模块发布和版本控制工作流程

本文翻译自《Module release and versioning workflow》。

目录

常见的工作流程步骤

针对未发布的模块进行编程

发布预发布(pre-release)版本

发布第一个(不稳定的)版本

发布第一个稳定版本

发布Bug修复

发布不破坏API的更改

发布破坏API的更改

当你开发供其他开发人员使用的模块时,你可以遵循有助于使用该模块的开发人员获得可靠、一致的体验的工作流程。本主题描述了该工作流程中的高级步骤。

有关模块开发的概述,请参阅开发和发布模块

也请参阅

  • 如果你只想在代码中使用外部包,请务必查看管理依赖项
  • 对于每个新版本,你都用其版本号表示对模块的更改。有关更多信息,请参阅模块版本编号

常见的工作流程步骤

以下序列说明了一个新模块的发布和版本控制的工作流程步骤。有关每个步骤的更多信息,请参阅本主题中的各个章节。

1 开始一个模块并组织它的源代码,使开发人员更容易使用,使你更容易维护。

如果你是开发模块的新手,请查看教程:创建Go模块

在Go的去中心化模块发布系统中,如何组织代码很重要。有关更多信息,请参阅管理模块源代码

2 开始编写调用未发布模块中的函数的本地客户端代码

在发布模块之前,它不能用于使用go get等命令的典型的依赖管理工作流程。在此阶段测试模块代码的一个好方法是,在本地目录中调用并测试它的代码。

有关本地开发的更多信息,请参阅下文的针对未发布的模块进行编程小节。

3 当模块的代码准备好供其他开发人员试用时,你可以开始发布alphas和beta等v0预发布版。有关详细信息,请参见下文的发布预发布(pre-release)版本小节。

4 发布一个v0版本,不保证稳定,但用户可以试用。有关详细信息,请参见下文的发布第一个(不稳定的)版本小节。

5 发布v0版本后,你可以(而且应该!)继续发布它的新版本

这些新版本可能包括bug修复(补丁版本)、对模块公开API的添加(次要版本),甚至是破坏性的更改。因为v0版本不保证稳定性或向后兼容性,所以你可以对其版本进行重大更改。

有关详细信息,请参见下文的发布Bug修复小节和发布不破坏API的更改小节。

6 当你准备好发布稳定版本时,你可以将预发布版本发布为alphas版本或beta版本。有关详细信息,请参见下文的发布预发布(pre-release)版本小节。

7 发布v1作为第一个稳定版本

这是第一个对模块稳定性做出承诺的版本。有关详细信息,请参见下文的发布第一个稳定版本小节。

8 在v1版本中,继续修复bug,并在必要时添加模块的公共API。

有关详细信息,请参见下文的发布Bug修复小节和发布不破坏API的更改小节。

9 当无法避免时,在一个新的主版本中发布破坏性的更改。

主版本更新——例如从v1.x.x到v2.x.x——对于模块的用户来说可能是一个非常具有破坏性的升级。这应该是最后的手段。有关更多信息,请参阅下文的发布破坏API的更改小节。

针对未发布的模块进行编程

当你开始开发模块或模块的新版本时,你还没有发布它。在发布模块之前,你将无法使用Go命令将该模块添加为依赖项。相反,当你在另一个模块中编写调用这个未发布模块的函数的客户端代码时,你首先需要在本地文件系统里引用该模块的副本。

你可以使用客户端模块的go.mod文件中的replace指令从本地引用该模块。有关更多信息,请参阅在本地目录中需求模块代码

发布预发布(pre-release)版本

你可以发布预发布版本,使模块可供其他人试用并向你提供反馈。预发布版本不保证稳定性。

预发布版本号后附有预发布标识符。有关版本号的更多信息,请参见模块版本号

以下是两个例子:

v0.2.1-beta.1
v1.2.3-alpha

在提供预发布版本时,请记住,使用预发布版本的开发人员需要使用go get命令按版本号明确指出它。这是因为,在默认情况下,go命令在定位你需求的模块时更喜欢正式的发布版本而不是预发布版本。因此,开发人员必须通过显式地指出来获得预发布版本,如下例所示:

go get example.com/[email protected]

你可以通过给存储库中的模块代码加标签来发布预发布版本,并在标签中指定预发布标识符。有关更多信息,请参阅发布模块

发布第一个(不稳定的)版本

当你发布预发布版本时,你可以发布不保证稳定性或向后兼容性的发布版本,但给你的用户一个试用该模块并向你提供反馈的机会。

不稳定版本是指版本号在v0.x.x范围内的版本。v0版本不保证稳定性或向后兼容性。但它为你提供了一种方法,可以在使用v1和更高版本做出稳定性承诺之前获得反馈并改进你的API。有关更多信息,请参见模块版本编号

与其他已发布版本一样,你可以在发布稳定的v1版本之前进行更改代码时增加v0版本号的次版本号和补丁版本号部分。例如,在发布v.0.0.0版本之后,你可能会发布带有第一组Bug修复的v0.0.1版本。 这是一个示例版本号:

v0.1.3

你可以通过给存储库中的模块代码加标签来发布不稳定版本,并在标签中指定v0版本号。有关更多信息,请参阅发布模块

发布第一个稳定版本

你的第一个稳定版本将具有v1.x.x版本号。第一个稳定版本是在预发布版本和v0版本之后发布的,你可以通过它们获得反馈、修复Bug并为用户稳定模块。

在v1版本中,你向使用你的模块的开发人员做出以下承诺:

  • 他们可以升级到主版本号后续的次版本和补丁版本,而不会破坏自己的代码。
  • 你不会对模块的公共API进行进一步的更改——包括它的函数和方法签名——这会破坏向后兼容性。
  • 你不会删除任何导出的类型,因为这会破坏向后兼容性。
  • 未来对API的更改(例如向结构体添加新字段)将向后兼容,并将包含在新的次版本中。
  • Bug修复(例如安全修复)将包含在补丁版本中或作为次版本的一部分。

注意:虽然你的第一个主版本可能是v0版本,但v0版本并没有稳定性或向后兼容性保证。因此,当你从v0升级到v1时,你无需注意破坏向后兼容性,因为v0版本被认为是不稳定的。

有关版本号的更多信息,请参阅模块版本编号。 下面是一个稳定版本号的例子:

v1.0.0

你通过给存储库中的模块代码加标签来发布第一个稳定版本,并在标签中指定v1版本号。有关更多信息,请参阅发布模块

发布Bug修复

你可以发布一个版本,其中的更改仅限于Bug修复。这称为补丁版本。

补丁版本仅包含较小的更改。特别是,它没有对模块的公开API进行任何更改。使用代码的开发人员可以安全地升级到这个版本,而无需更改他们的代码。

注意:你的补丁版本应该尽量不要将任何该模块自己的依赖项升级超过补丁版本。否则,升级到该模块补丁版本的人可能会意外地对他们使用的间接依赖项进行更具侵入性的更改。

补丁版本会增加模块版本号的补丁部分。有关更多信息,请参阅模块版本编号

在以下示例中,v1.0.1是一个补丁版本。

旧版本:v1.0.0

新版本:v1.1.0

你可以通过给存储库中的模块代码加标签来发布次要版本,增加标签中的次要版本号。有关更多信息,请参阅发布模块

发布破坏API的更改

你可以通过发布(major)版本来发布破坏向后兼容的版本。

主版本不保证向后兼容性,通常是因为它包含对模块公开API的更改,这些更改会破坏调用模块先前版本的代码。

考虑到主版本升级可能对依赖于模块的代码产生的破坏性影响,如果可以的话,你应该避免主版本更新。有关主版本更新的更多信息,请参阅开发主版本更新。有关避免进行破坏性更改的策略,请参阅博客文章保持模块兼容

如果发布其他类型的版本需要使用版本号来给模块代码加标签,那么发布主版本更新需要更多的步骤。

1 在开始开发新的主版本之前,在你的存储库中为新版本的源代码创建一个位置。

一种方法是在存储库中创建一个新的分支,专门用于新的主版本及其后续的次版本和补丁版本。有关更多信息,请参见管理模块源代码。 2 在模块的go.mod文件中,修改模块路径以附加新的主版本号,如下例所示:

example.com/mymodule/v2

既然模块路径是模块的标识,此更改有效地创建了一个新模块。它还更改了包路径,确保开发人员不会无意中导入破坏其代码的版本。相反,那些想要升级的用户将显式地用新路径替换旧路径。

3 在你的代码中,更改你正在更新的模块里的任何包的导入路径,包括你正在更新的模块里的包。你需要这样做,因为你更改了模块路径。

4 与任何新版本一样,在发布正式版本之前,你应该发布预发布版本以获得反馈和Bug报告。

5 通过在存储库中给模块代码加标签,增加标签中的主版本号(例如从v1.5.2到v2.0.0),发布新的主版本。

有关详细信息,请参见发布一个模块