去更新所有模块

Go update all modules

以这个模块为例(使用特定的提交以便其他人看到 我看到了什么):

git clone git://github.com/walles/moar
Set-Location moar
git checkout d24acdbf

我想要一种告诉 Go 去“更新一切”的方法。假设模块 将使用最新版本的所有内容。以下是我发现的五种方法 这样做,假设每个都是 运行 在一个干净的克隆上。这导致 go.mod 为 19 行:

go get -u

这导致 go.mod 14 行:

go get -u
go mod tidy

这导致 go.mod 13 行:

go mod tidy

如果我只是手动删除 require 和 运行 go mod tidy 中的所有内容,我会得到 12 行。如果我只是手动删除 require 和 运行 go get -u 中的所有内容,我会得到 11 行。我的问题是,为什么这些方法会产生不同的结果 结果,以及做我想做的事情的“正确方法”是什么?

tl;博士;

这就是你想要的:

go get -u
go mod tidy

并递归更新任何子目录中的包:

go get -u ./...

您看到的不一致是由于软件固有的有机性质造成的。

使用您的示例,维护者很可能在没有 运行 go mod tidy 的情况下签入 d24acdbf of git://github.com/walles/moar(解释较长的 19 行)。如果维护者有,那么您会看到最后看到的 13 行版本。

go get -u 本身在引入依赖性方面更积极。此外,将依赖项更新到最新(兼容)版本这一事实本身可能会引入新的 direct/indirect 依赖项。如果您明天尝试此操作,这些依赖项可能会进一步增长(某些子依赖项的最新版本添加了新功能,因此它需要新的依赖项)。因此,回购维护者修复特定(非最新)版本可能是有正当理由的。

go mod tidy 清除这种激进的依赖性分析。

P.S。一个常见的误解是依赖关系会在 go mod tidy 之后缩小:跟踪 go.sum,在某些情况下,这个文件会在 tidy 之后增长(尽管在这种情况下不是)

运行 go get -u && go mod tidy 1

更多详情:

  • go get -u(与 go get -u . 相同)更新当前目录中的包,因此更新提供该包的模块及其对 的依赖更新的次要版本或补丁版本可用时。 在典型项目中,运行 模块根目录中的这个就足够了,因为它可能会导入其他所有内容。

  • go get -u ./... 将扩展到以当前目录为根的所有包,这实际上也更新了所有内容(提供这些包的所有模块)。

  • 根据上面的内容,go get -u ./foo/... 将更新植根于 ./foo

    的所有内容
  • go get -u all 更新所有内容包括测试依赖项;来自 Package List and Patterns

When using modules, all expands to all packages in the main module and their dependencies, including dependencies needed by tests of any of those.

go get 还将向 go.mod 文件添加 require 指令以用于刚刚更新的依赖项。

  • go mod tidy 确保 go.mod 与模块 中的源代码匹配。在您的项目中,它产生 12 行,因为这些是与源代码匹配的最低限度。

  • go mod tidy 将通过删除不必要的校验和和传递依赖性(例如 // indirect),由于更新的 semver 可用,由 go get -u 添加。它还可能将缺失的条目添加到 go.sum.


注意从Go 1.17开始,在go.mod中新增间接依赖是


1:更新依赖项的最新 minor/patch 版本,go.modgo.sum