Go Modules: finding out right pseudo-version (vX.Y.Z-<timestamp>-<commit>) of required package
Update
This command is the better solution to adding the replace
command to go.mod
rather than doing it manually using git
that I initially posted:
go mod edit -replace github.com/docker/docker=github.com/docker/engine@ea84732a7725
produces a similar result but instead of using a pseudo-version, it finds the tagged engine version.
replace github.com/docker/docker => github.com/docker/engine v17.12.0-ce-rc1.0.20191113042239-ea84732a7725+incompatible
Alternatively, include a tagged docker version.
go mod edit -replace github.com/docker/[email protected]=github.com/docker/engine@ea84732a7725
for
replace github.com/docker/docker v1.13.1 => github.com/docker/engine v17.12.0-ce-rc1.0.20191113042239-ea84732a7725+incompatible
Thanks to @Shivam010 on Medium
Original, deprecated answer
Here's how I did it.
Checkout the repository on the desired branch/tag. e.g.
git clone -b v19.03.5 [email protected]:docker/engine.git
Then
cd engine
TZ=UTC git --no-pager show \
--quiet \
--abbrev=12 \
--date='format-local:%Y%m%d%H%M%S' \
--format="%cd-%h"
And i get
20191113042239-ea84732a7725
For use in go.mod
as
replace github.com/docker/docker v1.13.1 => github.com/docker/engine v0.0.0-20191113042239-ea84732a7725
A version of the form v0.0.0-20180906233101-161cd47e91fd
means that there are no tagged versions on the git repository. So go mod
generates one based on the latest commit time and the prefix of the commit hash.
To get a correct go.mod
file start out using the following command (assuming go 1.11):
go mod init yourmodulename
Or create an empty go.mod file that just contains the following:
module yourmodulename
then run go mod tidy
, this will find all dependencies, add the missing and remove the unused dependencies.
The author is using version strings like v0.0.0-20170922011244-0744d001aa84, consisting of the semver indication v0.0.0, a timestamp and something that looks like a git commit ID.
How do I figure out those version strings?
You never need to manually figure out those complex version strings, which are called pseudo-versions.
Daily workflow
Your typical daily workflow can be:
- Add import statements to your
.go
code as needed. - Standard commands like
go build
,go test
, orgo mod tidy
will automatically add new dependencies as needed to satisfy imports (updatinggo.mod
and downloading the new dependencies). By default, the@latest
version of a new direct dependency will be used. - When needed, more specific versions of dependencies can be chosen with commands such as:
go get [email protected]
go get foo@e3702bed2
go get foo@latest
go get foo@branch
- or by editing
go.mod
directly.
Note that you did not need to come up with a pseudo-version on your own in any of those examples, even when requesting a specific commit (e.g., @e3702bed2
), or the latest commit on a branch (e.g., @master
).
When do I see pseudo-versions in my go.mod
?
If you end up with a version that resolves to a valid semver tag with a leading v
such as v1.2.3
or v1.2.4-beta-1
, then that semver tag will be recorded in your go.mod
file. If the version does not have a valid semver tag, then it will be instead recorded with as a pseudo-version in your go.mod
file, such as v0.0.0-20171006230638-a6e239ea1c69
, which includes a version section, a commit timestamp, and a commit hash.
In your particular case, golang.org/x/net/html
does not have any semver tags, which means if you do go get golang.org/x/net/html@latest
, or go get golang.org/x/net/html@0744d001aa84
, or just do go build
after first including import "golang.org/x/net/html"
in your .go
file, then golang.org/x/net/html will be recorded in your go.mod
as a pseudo-version, but note that you did not need to figure out the complex string yourself (because the go
command translates modules queries such as go get golang.org/x/net/html@0744d001aa84
into the corresponding pseudo-version when needed, and records the result in your go.mod
).
Why was the pseudo-version format chosen?
The pseudo-version format helps provide a simple total ordering across all versions based on standard semver ordering, which makes it easier to reason about what commit will be considered "later" than another commit, or whether an actual semver tag is considered "later" than a separate commit.
Controlling dependency versions
You can read more about all of the above in the "How to Upgrade and Downgrade Dependencies" section of the Go Modules wiki, which also contains additional links into the official documentation.