Repository navigation
auth git-credential fails if username provided by git does not match active user #11938
Description
Activity
- addedenhancementa request to improve CLIa request to improve CLIauthrelated to tokens, authentication state, or oauthrelated to tokens, authentication state, or oauthgh-authrelating to the gh auth commandrelating to the gh auth commandand removedbugSomething isn't workingSomething isn't working
on Oct 15, 2025 github-actions commented
on Oct 15, 2025 on Oct 15, 2025 – with GitHub ActionsContributorMore actionsThank you for your issue! We have categorized it as a feature request, and it has been added to our backlog. In doing so, we are not committing to implementing this feature at this time, but, we will consider it for future releases based on community feedback and our own product roadmap.
Unless you see the help wanted
Contributions welcome label, we are not currently looking for external contributions for this feature.If you come across this issue and would like to see it implemented, please add a thumbs up! This will help us prioritize the feature. Please only comment if you have additional information or viewpoints to contribute.
FYI. I also submitted a PR to address this issue. #11937
Hi @cavanaug! 👋 And thanks for opening up an issue! 🙏
I haven't yet fully digged this, but as far as I can tell from the
auth git-credentialcommand implementation, it seems like it doesn't support multiple usernames per host, althoughghdoes support this.We need to look more into this and make sure it's possible to improve
auth git-credentialwithout breaking any behaviour (See my notes below). As for your PR, I'm afraid I have to close it for now, as an open PR means it has to be reviewed, while we haven't yet decided if/how we want to implement this. That's why we advise against submitting PRs before an issue is fully triaged and marked with help wantedContributions welcome . Anyway, I appreciate your effort you put into this and that definitely provide insight for later implementation. 🙏Now, as a workaround to unblock you, I'm wondering if such a change would help with your case:
[credential "https://github.com/"] username = dilberthome helper = helper = !gh auth git-credential [credential "https://github.com/acme-main/"] username = dilbertwork_acme helper = helper = !GH_TOKEN="$(gh auth token --hostname github.com --user dilbertwork_acme)" gh auth git-credential
Basically, we're just overriding the behaviour by opting to a temporarily set
GH_TOKENenv var.Can you please try this and let me know if it helps?
Notes on potential implementation
This seems to be slipped through our hands back when multiple account support was added. I'm not sure yet, and I have to dig deeper into the repo history to see if there's a sound reason for this behaviour. Assuming there isn't, this seems like a plausible addition.
Basically, Git can include a
usernamein the input toauth git-credentialand we should return the credentials associated with that username, instead of always picking the active user for the givenhost. Currently, we bail out if the givenusernamedoes not match the active user. Needless to say we have to see if there's a specific reason behind such a restriction.Reacted by Carlin Scott- addedmore-info-neededMore info needed from user/contributorMore info needed from user/contributor
on Oct 22, 2025 Just a few comments for future reference.
The challenge is how to semi-cleanly integrate GH across personal and work in a sane fashion additionally supporting multiple GH enterprise instances. Folks want tools like git/lazygit/etc and gh cli to "just work" for both work and personal situations.
Ive had a heck of a time making all this work. gh-cli is really centered around tokens and sort of has users as a bit of an afterthought. GitHub itself is not super set up for multiple accounts on the same repos. Ssh is a mess because you cant really dynamically configure things by folder unless you do some magic in .gitconfig to explicitly list which ssh key to use.
Technically some of this defect could be side stepped with a shell script replacement for git-credential that does the right thing and calls gh cli under the hood. But that is then a private script and integration would always be better.
The bottom line is securely handling tokens/auth for git & gh-cli and such across multiple accounts and github instances is just sort of broken and its not really anyones fault, things just evolved and we ended up where we are today and folks are trying to glue together some pieces/strategies/conventions that will work for folks that dont have a black belt in linux/bash/git/gh.
Id love to be able to help with this. Hit me up whenever, my company (HPI) has a large migrations of like 100k repos and thousands of users to GH. I can work on this as part of my company role as well.
Reacted by Babak K. Shandiz and Christopher Sullivan- removedmore-info-neededMore info needed from user/contributorMore info needed from user/contributor
on Oct 23, 2025 - changed the title
[-]gh auth git-credential doesnt respect username from config file[/-][+]`auth git-credential` fails if `username` provided by git does not match active user[/+]on Oct 23, 2025 I came at this problem from a different direction, looking to make it automatic to use my non-personal account for any repo in the non-personal org, and my personal account for everything else. I implemented it in a PR, that was of course automatically closed, but wanted to add it here as a reference as well.
I set it up so that you can add a mapping of owner -> user, and then any repo with a configured owner will use the mapped user via the factory created http client. If there is not an owner->user match, it will use the globally active one. This allows me to leave it as my personal account in general, but ensures that when I need to interact with a non-personal repo, I'm using the correct credential.The solutions suggested here are good solutions if the repos are segregated by directory easily. That wasn't the case for me, so the owner path seemed the most straightforward.
Adding a concrete reproduction, since the thread so far describes the behaviour but doesn't demonstrate it. Tested on
gh2.97.0 with two accounts logged in togithub.com(user-a,user-b).With
user-aactive:$ printf 'protocol=https\nhost=github.com\nusername=user-a\n\n' | gh auth git-credential get protocol=https host=github.com username=user-a password=gho_*** $ printf 'protocol=https\nhost=github.com\nusername=user-b\n\n' | gh auth git-credential get $ echo $? 1 $ printf 'protocol=https\nhost=github.com\n\n' | gh auth git-credential get # -> returns user-a's credential
Then
gh auth switch -u user-band repeat:$ printf 'protocol=https\nhost=github.com\nusername=user-b\n\n' | gh auth git-credential get # -> now succeeds $ printf 'protocol=https\nhost=github.com\nusername=user-a\n\n' | gh auth git-credential get $ echo $? 1
So the requested
username=is used purely as an assertion against the globally active account, never as a selector. The same request flips from success to exit 1 depending only on global state that the repository has no control over.The practical consequence is that the documented per-repo pattern is inert whenever
ghis the configured helper:[credential "https://github.com"] username = user-b
gh auth setup-gitinstalls a host-scopedhelper = !gh auth git-credentialentry (preceded by a blankhelper =reset), so this affects anyone who ran it and later added a second account — which is the normal path into a multi-account setup.Where it happens —
pkg/cmd/auth/gitcredential/helper.go:// resolves the *active* account, ignoring wants["username"] entirely gotToken, source := cfg.ActiveToken(lookupHost) // ~L115 gotUser, _ = cfg.ActiveUser(lookupHost) // ~L124 // username= is only ever compared, never used to look anything up if wants["username"] != "" && gotUser != tokenUser && !strings.EqualFold(wants["username"], gotUser) { return cmdutil.SilentError // ~L134 }
AuthConfig.TokenForUser(hostname, user)already exists and does exactly the lookup needed here, so the change is roughly: whenwants["username"]is non-empty and doesn't match the active user, tryTokenForUserbefore giving up, and only returnSilentErrorif that also fails. Env-sourced tokens (*_TOKEN, wheregotUser == tokenUser) should keep short-circuiting as they do now. That preserves current behaviour in every single-account and env-token case.@babakks — this matches your Oct 2025 read that the helper "doesn't support multiple usernames per host, although
ghdoes support this". #11937 was closed pending a wider look; it could be rebased onto theTokenForUserapproach if that's the preferred shape.For orientation, this is one of two independent halves of the multi-account problem:
- this issue —
gitHTTPS operations through the credential helper; - #13768 —
gh's own commands (gh pr create,gh api) picking an account from context; - #12885 — the shared prerequisite, since keyring lookup keys on service only and returns an arbitrary entry when several accounts share a host.
Worth noting that fixing only #13768 would leave
gh pr createusing the correct account whilegit pushin the same directory still fails or pushes as the wrong identity — PR #13781 wraps the factory's HTTP token getter, which this helper doesn't go through. This issue needs its own fix either way.- this issue —
Follow-up, since I found something that narrows this further: the lookup this issue needs isn't just present internally — it's already exposed as a supported, documented flag, and it already works for a non-active account.
Retested on
gh2.98.0, two accounts ongithub.com, withuser-aactive:$ gh auth token --user user-b # the non-active account gho_**************************** # -> exit 0, 40-char token $ GH_TOKEN=$(gh auth token --user user-b) gh api user --jq .login user-b # -> resolves as the right identity $ gh api user --jq .login # unset, i.e. the active account user-a
Meanwhile the credential helper, same machine, same moment, same account:
$ printf 'protocol=https\nhost=github.com\nusername=user-b\n\n' | gh auth git-credential get $ echo $? 1
That's the whole issue in four commands.
ghcan already retrieve a non-active account's token on demand and act as that identity;auth git-credentialis the one path that can't.pkg/cmd/auth/token/token.go(~L83) reaches this viaauthCfg.TokenForUser(hostname, opts.Username)— the sameAuthConfig.TokenForUser(internal/config/config.go:515) I referenced above. So the helper isn't missing a capability, it's just not calling one that already ships, is already user-facing, and is already proven correct on this platform.Two things follow:
- Scope. This is a plumbing gap, not new functionality. The fix reuses an existing primitive rather than introducing a resolution strategy, so it can't regress storage or token-resolution behaviour, and it doesn't depend on the broader design discussion in Better multi-account
ghaccount usage #13768 / Automatic Account Selection for Multi-Account Workflows #12697 landing first. - Risk. Every single-account setup and every env-token (
*_TOKEN) case keeps hitting the existing active-account path unchanged; the new lookup only runs where the helper returns exit 1 today.
Reacted by John Cavanaugh- Scope. This is a plumbing gap, not new functionality. The fix reuses an existing primitive rather than introducing a resolution strategy, so it can't regress storage or token-resolution behaviour, and it doesn't depend on the broader design discussion in Better multi-account
Describe the bug
I have a scenario where I have both a personal and work github account, each with different usernames/tokens etc.
I wanted to configure things as the following in my .gitconfig
Affected version
gh version 2.81.0 (2025-09-30)
https://github.com/cli/cli/releases/tag/v2.81.0
Steps to reproduce the behavior
Expected vs actual behavior
Given that I have specified the proper username in my gitconfig I would expect that the configured username is used for the git-credential lookup. Which it does not.
In essence I would expect it to behave similarly to
gh auth token --user xxxx --hostname yyyy
Logs
Paste the activity from your command line. Redact if needed.