Go update all modules
Asked Answered
R

5

164

Using this module as an example (using a specific commit so others will see what I see):

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

I would like a way to tell Go to "update everything". Assume that the module will work with the newest version of everything. Below are five ways I found to do this, assume each is run on a clean clone. This results in a go.mod of 19 lines:

go get -u

This results in a go.mod of 14 lines:

go get -u
go mod tidy

This results in a go.mod of 13 lines:

go mod tidy

If I just manually delete everything in require and run go mod tidy, I get 12 lines. If I just manually delete everything in require and run go get -u, I get 11 lines. My question is, why are these methods producing different results, and what is the "right way" to do what I am trying to do?

Romeu answered 21/4, 2021 at 18:39 Comment(0)
M
294

tl;dr;

this is what you want:

go get -u
go mod tidy

and to recursively update packages in any subdirectories:

go get -u ./...

The inconsistencies you are seeing is due to the inherent organic nature of software.

Using your example, commit d24acdbf of git://github.com/walles/moar most likely was checked in by the maintainer without running go mod tidy (explaining the longer 19 lines). If the maintainer had, then you would see the 13 line version you see at the end.

go get -u on it's own is more aggressive in pulling in dependencies. Also, the mere fact of updating dependencies to their latest (compatible) version, may in & of itself pull in new direct/indirect dependencies. These dependencies may grow even further if you tried this tomorrow (the latest version of some sub-dependency adds new functionality, so it needs new dependencies). So there may be a valid reason the repo maintainer fixes at a particular (non-latest) version.

go mod tidy cleans up this aggressive dependency analysis.

P.S. It's a common misconception that dependencies will shrink after go mod tidy: tracking go.sum, in some cases this file will grow after a tidy (though, not in this case)

Mckeever answered 21/4, 2021 at 19:45 Comment(1)
At one time go get -u upgraded all of the module dependencies of the modules containing the named packages, but in practice that ended up upgrading way too many irrelevant modules, so we narrowed it in Go 1.13: see golang.org/doc/go1.13#go-get.Goldarn
W
56

Run go get -u && go mod tidy 1

More details:

  • go get -u (same as go get -u .) updates the package in the current directory, hence the module that provides that package, and its dependencies to the newer minor or patch releases when available. In typical projects, running this in the module root is enough, as it likely imports everything else.

  • go get -u ./... will expand to all packages rooted in the current directory, which effectively also updates everything (all modules that provide those packages).

  • Following from the above, go get -u ./foo/... will update everything that is rooted in ./foo

  • go get -u all updates everything including test dependencies; from 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 will also add to the go.mod file the require directives for dependencies that were just updated.

  • go mod tidy makes sure go.mod matches the source code in the module. In your project it results in 12 lines because those are the bare minimum to match the source code.

  • go mod tidy will prune go.sum and go.mod by removing the unnecessary checksums and transitive dependencies (e.g. // indirect), that were added to by go get -u due to newer semver available. It may also add missing entries to go.sum.


Note that starting from Go 1.17, newly-added indirect dependencies in go.mod are arranged in a separate require block.


1: updates dependencies' newest minor/patch versions, go.mod, go.sum

Wisniewski answered 21/4, 2021 at 19:47 Comment(0)
S
27

There are some hidden dragons, here is what I recommend:

  • go get -u ./... walks all packages in your project. This is the command you want to use.
  • go get -t -u ./... walks all packages in your project and also downloads tests files of these dependencies. Probably you don’t need that.
  • go get -u updates in the current directory only. Useful for small single-package projects, just use the first version.
  • go get -u specific.com/package updates just one (or more separated by space) packages (and dependencies).
  • go get -u specific.com/package@version the same but to a specific version.
  • go get -u all updates modules from the build list from go.mod. This is useful for listing (go list -m -u all) but not too useful for updates.
Sik answered 17/2, 2023 at 10:17 Comment(0)
W
10

This is also an option: go-mod-upgrade, an interactive prompt. It highlights patches in yellow and breaking changes in red :)

sample

Weak answered 17/5, 2023 at 21:20 Comment(0)
U
1

tldr: use go get -u ./... for latest Go versions

Accepted answer as well as highly ranked answers with go get -u no longer work with latest go version.

According to this (1) cmd Go issue, the suggested option is to use go get -u -d ./...

If you want to update the dependencies of all packages within a module, you want go get -u -d ./....

(1) - https://github.com/golang/go/issues/37700

Underthrust answered 27/3 at 16:39 Comment(1)
This is incorrect, and the linked Go issue is not relevant. The -d flag simply instructs the command to not build/install the packages, and since Go 1.18 is enabled by default. reference. Therefore with modern Go versions, adding or not adding the -d flag gives the same result.Wisniewski

© 2022 - 2024 — McMap. All rights reserved.