Git标签必须以v开头并严格遵循SemVer格式(如v1.2.3),否则go工具链无法识别;v2+版本还需同步更新module路径和所有import语句为/v2形式,并显式推送tag到远程。

git tag 必须带 v 前缀且格式严格匹配 SemVer
Go 工具链只认 vMAJOR.MINOR.PATCH 格式的标签,比如 v1.2.3。写成 1.2.3、v1.2、v1.2.3-rc(没加点号后缀)或 v1_2_3,go list -m -versions 就看不到它。
常见踩坑点:
- 本地用
git tag 1.2.0—— 缺v,Go 直接忽略 - CI 脚本里拼错标签名,比如
git tag v${VERSION}但$VERSION是空值,结果打成v—— 无效标签 - 误用预发布格式如
v1.2.3-beta:默认不显示在go list结果里,得加-pre参数才可见,不适合正式发布
打 v1.0.0 前必须改 module 路径并推送含 go.mod 的 commit
不是“打了 tag 就完事”。v1.0.0 发布前,go.mod 文件里的 module 行必须已更新为最终路径(如 github.com/user/repo),且该文件已提交到 Git,并被推送到远端主分支。
否则会出现两种典型问题:
-
go list -m -json github.com/user/repo@v1.0.0返回Version: "(devel)"—— 说明 Go 没解析到有效版本 - 下游执行
go get github.com/user/repo@v1.0.0报unknown revision v1.0.0或unrecognized import path—— 因为 tag 指向的 commit 里没有go.mod,或路径不匹配
验证命令:go list -m -json github.com/user/repo@v1.0.0 | jq .Version,输出应为 "v1.0.0",不是 "(devel)"。
v2+ 版本必须同步改 module 路径和所有 import
v2 开始,Go 强制要求模块路径包含主版本后缀,比如从 github.com/user/repo 升级到 v2,go.mod 必须改成 github.com/user/repo/v2,且所有内部 import 语句也得手动改成带 /v2 的路径。
不改路径只打 v2.0.0 标签,会触发错误:
invalid version: module contains a go.mod file, so major version must be compatible- 旧导入路径(
github.com/user/repo)和新路径(github.com/user/repo/v2)被 Go 视为两个完全独立的模块,无法自动迁移
注意:replace 指令不能用于跨 major 版本混用,否则 go build 可能静默失败或行为异常。
tag 推送漏掉 git push origin v1.0.0 就等于没发布
git tag v1.0.0 只是本地操作。必须显式运行 git push origin v1.0.0(不是 git push --tags,后者可能把测试用的临时标签也推上去)。
Go 生态消费的是远程仓库的标签,不是你本地的。没推送,其他开发者或 CI 环境执行 go get 时就会卡住或报错。
容易被忽略的细节:
- GitHub/GitLab 页面上能看到 tag,不代表它已被 Go 工具链识别——要等
proxy.golang.org或你配置的代理(如goproxy.cn)抓取该 tag 对应的 commit hash - 私有仓库需提前配置
GOPRIVATE,否则go get会跳过认证直接走公共代理,导致失败 - 打 tag 的 commit 必须是含有效
go.mod的干净提交;如果该 commit 里go.mod被replace或exclude干扰,go list仍可能返回异常

















