Skip to content

proposal: cmd/go: go list -m should report VCS-derived version for the main module #79789

Description

@huww98

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 LookupLocalrepo.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

  1. 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.

  2. Non-Go tooling — shell scripts, Makefiles, and release pipelines that need the module version without invoking a full build.

  3. Quick inspectiongo 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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    No status

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions