fix(cmdutils): resolve same-host SSH remotes to the right account
Description
When two accounts are configured for the same instance — the second keyed under a synthetic host (for example, gitlab.com-work with api_host: gitlab.com and ssh_host: gitlab.com) whose SSH alias resolves, through ~/.ssh/config, to the shared host — a repository cloned over the SSH alias resolved to the primary account. Repo-scoped commands then acted as the wrong account and returned 404 on the second account's private projects.
The root cause is ordering: the remote resolver ran every SSH remote through ~/.ssh/config translation before matching it against the configured hosts, so an alias was rewritten to the shared host (bound to the primary account) and the second account's entry was never reached. HTTPS remotes were unaffected, because they match literally.
This change establishes the same precedence HTTPS already uses: a remote whose literal SSH host is already a configured host — a config key or an entry's ssh_host — resolves to that account, and only genuinely unknown hosts fall back to ~/.ssh/config translation. The ssh_host lookup map and the remote-host probe are normalized (glinstance.NormalizeHostname); config keys are matched verbatim, since config host lookups are case-sensitive.
Beyond the #8394 (closed) multi-account case, the same precedence fixes two setups that error out on main today:
- a configured host aliased away in
~/.ssh/configwith nossh_hostset — the alias rewrote the host to an unknown one, so no remote matched; gitlab.comaliased to a non-official SSH endpoint such as a corporate proxy — previously onlyssh.gitlab.com/altssh.gitlab.comwere preserved.
With this precedence in place, the gitlabComSSHAliases allowlist added in 6c7b7d23 is unreachable from its only production caller (knownHosts always contains gitlab.com, so a gitlab.com remote returns before the translator runs), so it, its Translator() branch, and its tests are removed.
Only remotes whose literal host is a configured host change behavior; every other remote resolves exactly as before.
Related Issues
Resolves #8394 (closed)
How has this been tested?
- Rebased onto
main(cherry-picks cleanly); the branch is now one commit ahead. Test_remoteResolverSameHostSSHAliasis now table-driven and covers: the #8394 (closed) second same-host account (verbatim config, including itsssh_host: gitlab.comline), the primary account still resolving over the shared host, a genuine alias for an unknown host still translating (the fallback branch), the two setups that error onmainand now work, anssh_hostvalue matched before translation, and a mixed-casessh_hostvalue (normalisation of thessh_hostmap).- The resolver gained a
parseSSHConfig func() git.SSHAliasMapseam, defaulted togit.ParseSSHConfiginfactory.go; tests inject a fixed alias map, so they no longer mutateHOME/USERPROFILEor read the developer's real~/.ssh/config. go test ./...— all green (291 packages, 0 failures), includinginternal/gitafter removing thealtsshtranslator cases.go vet ./...andgofmtare clean;go build ./cmd/glabsucceeds.
Environment: Go 1.26.5 (the version pinned in .tool-versions), Linux.