Golang中go get命令为何不再遵循ssh git.url.insteadOf配置?

Golang中go get命令为何不再遵循ssh git.url.insteadOf配置? 我有一个全局的 git 设置:

[url "git@bitbucket.org:"]
    insteadOf = https://bitbucket.org/

并且没有本地覆盖或重写。最近,对我自己、我组织中的一些其他人以及我们所有的自动化流水线来说,go get 似乎已经不再遵守这个设置了。如果我运行 go get -x bitbucket.org/organizationname/foo,我看到的是:

# get https://api.bitbucket.org/2.0/repositories/organizationname/foo?fields=scm
# get https://api.bitbucket.org/2.0/repositories/organizationname/foo?fields=scm: 404 Not Found (0.568s)
# get https://proxy.golang.org/bitbucket.org/@v/list
# get https://proxy.golang.org/bitbucket.org/@v/list: 410 Gone (0.076s)
# get https://api.bitbucket.org/2.0/repositories/organizationname/foo?fields=scm
# get https://api.bitbucket.org/2.0/repositories/organizationname/foo?fields=scm: 404 Not Found (0.080s)
go get bitbucket.org/organizationname/foo: reading https://api.bitbucket.org/2.0/repositories/organizationname/foo?fields=scm: 404 Not Found

Go 版本是 go1.16 darwin/amd64(编辑:具体是 go1.16.0,这后来证明很重要),据我所知最近没有改变。我已经确认直接使用 git 命令,例如 git ls-remote git@bitbucket.org:organizationname/foo,可以正常工作并按预期显示分支。这里到底发生了什么?


更多关于Golang中go get命令为何不再遵循ssh git.url.insteadOf配置?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

6 回复

我最近在更新一个私有模块时遇到了与上面帖子中相同的错误。我的 GOPRIVATE 设置是正确的,并且之前使用 go get -x bitbucket.org/org/repo 是有效的。

我更新到 go1.18 后,问题得到了解决,现在 go get 对于私有仓库可以按预期工作了。

+1

更多关于Golang中go get命令为何不再遵循ssh git.url.insteadOf配置?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我之前也在使用 go1.16 darwin/amd64。我开始遇到与上面帖子中相同的错误,即在更新私有模块时。我的 GOPRIVATE 设置是正确的,并且之前使用 go get -x bitbucket.org/org/repo 是有效的。

我更新到 go1.18 后,问题得到了解决,现在 go get 对于私有仓库能按预期工作了。

所以我不太清楚为什么这对我来说开始成为一个问题,但升级似乎修复了它。

更新:Bitbucket 已经意识到此举让很多人非常愤怒,并被广泛认为是一个糟糕的举动(x),并且暂时撤销了这项更改。希望他们在再次实施之前,会遵循标准的弃用和发布警告的步骤。尽管如此,在此期间更新到 1.16.14/1.17.7/1.18.x 版本可能是明智的。

升级之所以有效,是因为Bitbucket在仅提前几天通知的情况下,停止为未正确认证的私有仓库返回403错误,转而用404错误替代。他们的理由(姑且这么说)在此处有描述。没有解释为什么他们认为在周三通过一个没人看的博客宣布一个破坏性变更,并在接下来的周四就采用,且不允许选择退出或提供有用的错误信息,这种做法是合理的。

Go 版本 1.16.14、1.17.7 和 1.18.x 更新了 go get 的行为,使其对 404 错误的响应方式与对 403 错误相同。这修复了该问题。祝那些突然需要更新 Go 版本以维持系统运行,并且在此过程中无法运行任何测试自动化的人好运。

你好,

第一眼就发现了两点问题。

  • go get 命令行没有指定版本标签。你是在一个存在 go.mod 文件的主模块内运行这个命令的吗?如果你在模块外部运行此命令,请尝试在模块路径后追加 @<version>,例如 @v1.2.3@latest
  • go get 命令在 Go 代理处也失败了。这个模块是私有的吗?如果是,请检查 GOPRIVATE 设置。如果模块是公开的,410 Gone 状态表明该模块尚未被代理缓存,至少没有缓存 go get 命令所请求的版本。同样,在模块路径后添加版本后缀可能会有帮助。 如果模块是公开的(因此应该已经被 Go 代理缓存),那么问题肯定与 SSH 无关,因为 Go 代理应该会通过 HTTPS 顺利交付该模块。

要测试 HTTPS 与 SSH 是否是这里的问题,你可能需要禁用 git 设置,并验证 git 是否能够通过 HTTPS 成功获取仓库。

这就是我目前能想到的所有建议,希望其中至少有一条能指引正确的方向。

Go 1.16 版本中,go get 命令的行为发生了变化,不再直接使用 Git 的 insteadOf 配置来重写 URL。从 Go 1.16 开始,go get 在获取模块时会优先使用 Go 模块代理(如 proxy.golang.org)和校验和数据库,而不是直接使用 Git 命令。这导致 Git 的 insteadOf 配置在某些情况下被忽略。

具体来说,当 go get 尝试获取模块时,它会先向模块代理发送请求,如果代理返回 404 或 410 错误,它会回退到直接使用版本控制系统(如 Git)获取。但在回退时,Go 工具链会使用内置的 HTTP 客户端,而不是直接调用 Git 命令,因此 Git 的 insteadOf 配置不会生效。

要解决这个问题,你可以使用 Go 模块的 GOPRIVATE 环境变量来指定私有模块,并配置 GIT_TERMINAL_PROMPTGIT_SSH 环境变量来强制使用 SSH 协议。以下是示例代码:

// 设置环境变量
export GOPRIVATE=bitbucket.org/organizationname
export GIT_TERMINAL_PROMPT=1
// 或者使用自定义 SSH 命令
export GIT_SSH=/path/to/ssh-custom-script

另外,你可以在 ~/.gitconfig 或项目中的 .git/config 文件中显式配置 SSH URL:

[url "git@bitbucket.org:"]
    pushInsteadOf = https://bitbucket.org/
    insteadOf = https://bitbucket.org/

如果问题仍然存在,可以尝试升级到 Go 1.17 或更高版本,因为后续版本对私有模块的支持有所改进。同时,确保你的 go env 配置正确,特别是 GOPRIVATEGONOSUMDB 设置:

go env -w GOPRIVATE=bitbucket.org/organizationname
go env -w GONOSUMDB=bitbucket.org/organizationname

最后,如果模块是私有的,确保在 go.mod 文件中正确声明了模块路径,并且 Bitbucket 仓库的访问权限已配置 SSH 密钥。

回到顶部