gop icon indicating copy to clipboard operation
gop copied to clipboard

Go modules pseudo-version based on old `v1.2.0-pre.1` instead of latest `v1.5.1`

Open aofei opened this issue 3 months ago • 0 comments

Description

When using go get to fetch a specific commit from the main branch, Go modules generates a pseudo-version based on v1.2.0-pre.1 (from 2023) instead of the latest release v1.5.1. This causes confusion and makes the version appear to be going backwards.

More importantly, this affects Go modules' Minimal Version Selection (MVS) algorithm. Since the pseudo-version v1.2.0-pre.1.0.xxx is semantically lower than v1.5.1, it causes problems:

  • When a project already uses [email protected], attempting to update to main branch appears as a downgrade
  • The pseudo-version (v1.2.0-pre.1.xxx) won't satisfy constraints like >=v1.5.0 even though the actual code is newer than v1.5.1
  • Users have to use replace directives to work around this issue
  • Automated dependency tools get confused (e.g., Dependabot incorrectly suggests "updating" from v1.2.0-pre.1.0.xxx to v1.5.1)

Steps to reproduce

  1. Try to get a specific commit that's on main branch
go list -m -json github.com/goplus/xgo@1c2f62eb363cadb2ebd4bdc3ec1de6c14e4d7183
  1. Observe the result
{
        "Path": "github.com/goplus/xgo",
        "Version": "v1.2.0-pre.1.0.20250906025243-1c2f62eb363c",
        "Query": "1c2f62eb363cadb2ebd4bdc3ec1de6c14e4d7183",
        "Time": "2025-09-06T02:52:43Z",
        "GoMod": "/Users/aofei/.cache/go/pkg/mod/cache/download/github.com/goplus/xgo/@v/v1.2.0-pre.1.0.20250906025243-1c2f62eb363c.mod",
        "GoVersion": "1.18"
}

The pseudo-version is based on v1.2.0-pre.1 even though the latest release is v1.5.1.

Root cause analysis

The issue stems from how the project's branching and tagging strategy interacts with Go modules' pseudo-version generation.

Current release workflow

  1. Development happens on main branch
  2. When releasing (e.g., v1.5.1), a PR is created from main to version branch (v1.5)
  3. After merging the PR, tags are created on the version branch
  4. The version branch and its tags remain separate from main's history

Git history structure

main branch:     v1.0.x → v1.1.x → v1.2.0-pre.1 → [continues development...]
                                         ↓
                                    (fork point)
                                         ↓
v1.5 branch:                       [PR merge] → v1.5.0 → v1.5.1
v1.4 branch:              [separate] → v1.4.0 → v1.4.5 → v1.4.6
v1.3 branch:     [separate] → v1.3.0 → v1.3.1 → v1.3.2

Why this causes problems

  • Go modules generates pseudo-versions based on the most recent ancestor tag in the Git history
  • Since v1.5.1, v1.4.x, v1.3.x tags are on separate branches (not ancestors of main)
  • The most recent tag that's an ancestor of main is v1.2.0-pre.1 (from 2023)
  • Therefore, any commit on main gets a pseudo-version based on this old tag

Verification

Check which tags are ancestors of main:

git tag --merged main | grep "^v" | sort -V | tail -5

Output shows the most recent version tag is v1.2.0-pre.1.

Check the base version for main branch:

git describe --tags main

Output shows v1.0.32-1195-g1c2f62eb, which is based on even older v1.0.32.

aofei avatar Sep 19 '25 11:09 aofei