Background
Since Go 1.24 (#50603), go build stamps VCS-derived pseudo-versions into binaries. This version is readable after building via go version -m <binary> or debug.ReadBuildInfo():
$ go build -o myapp .
$ go version -m myapp | grep mod
mod example.com/myapp v1.2.4-0.20250115103000-abcdef123456+dirty
However, there is no way to query this version without building. go list -m always reports an empty Version for the main module:
$ go list -m -json
{
"Path": "example.com/myapp",
"Main": true,
"Dir": "/home/user/myapp",
"GoMod": "/home/user/myapp/go.mod",
"GoVersion": "1.24"
}
Proposal
go list -m should populate the Version field for the main module using the same VCS-derived version logic that go build uses (the LookupLocal → repo.Stat path in cmd/go/internal/load/pkg.go:setBuildInfo).
$ go list -m -json
{
"Path": "example.com/myapp",
"Main": true,
"Version": "v1.2.4-0.20250115103000-abcdef123456+dirty",
"Dir": "/home/user/myapp",
...
}
This would be gated behind -buildvcs (defaulting to auto, same as go build) to avoid slowing down go list -m when VCS info is not wanted.
Use cases
-
CI/CD version stamping before build — scripts that need the version string to pass as -ldflags "-X main.version=...", tag Docker images, or populate release metadata. Currently this requires either building a throwaway binary or reimplementing the pseudo-version logic.
-
Non-Go tooling — shell scripts, Makefiles, and release pipelines that need the module version without invoking a full build.
-
Quick inspection — go list -m -json | jq -r .Version is significantly more convenient than building a temporary binary just to read its embedded version.
Evidence of demand
The lack of this feature has led to multiple third-party tools that reimplement Go's pseudo-version computation:
Each reimplements a subset of the toolchain's logic (tagPrefix, MatchPathMajor, IsPseudoVersion, retract filtering, +dirty, +incompatible) with varying degrees of correctness. The version computation is already implemented in the Go toolchain — exposing it via go list -m would eliminate the need for these tools entirely.
Related issues
Background
Since Go 1.24 (#50603),
go buildstamps VCS-derived pseudo-versions into binaries. This version is readable after building viago version -m <binary>ordebug.ReadBuildInfo():However, there is no way to query this version without building.
go list -malways reports an emptyVersionfor the main module:Proposal
go list -mshould populate theVersionfield for the main module using the same VCS-derived version logic thatgo builduses (theLookupLocal→repo.Statpath incmd/go/internal/load/pkg.go:setBuildInfo).This would be gated behind
-buildvcs(defaulting toauto, same asgo build) to avoid slowing downgo list -mwhen VCS info is not wanted.Use cases
CI/CD version stamping before build — scripts that need the version string to pass as
-ldflags "-X main.version=...", tag Docker images, or populate release metadata. Currently this requires either building a throwaway binary or reimplementing the pseudo-version logic.Non-Go tooling — shell scripts, Makefiles, and release pipelines that need the module version without invoking a full build.
Quick inspection —
go list -m -json | jq -r .Versionis significantly more convenient than building a temporary binary just to read its embedded version.Evidence of demand
The lack of this feature has led to multiple third-party tools that reimplement Go's pseudo-version computation:
golang.org/x/mod/module.PseudoVersionwith local git statecodehost/git.gomodule.PseudoVersionEach reimplements a subset of the toolchain's logic (
tagPrefix,MatchPathMajor,IsPseudoVersion, retract filtering,+dirty,+incompatible) with varying degrees of correctness. The version computation is already implemented in the Go toolchain — exposing it viago list -mwould eliminate the need for these tools entirely.Related issues
go build#50603 —cmd/go: stamp the pseudo-version in builds generated by go build(implemented in Go 1.24, but only accessible after building)runtime/debug: document BuildInfo.Main.Version == "(devel)"(long discussion about wanting version info without-ldflags)proposal: cmd/go: add -buildversion build flag(addresses package managers that know the version, but not the local VCS case)cmd/go: stamp git/vcs current HEAD hash/commit hash/dirty bit in binaries(VCS info stamping, precursor to cmd/go: stamp the pseudo-version in builds generated bygo build#50603)