Multiple GitHub accounts on one PC: gh, GCM and SSH
You have a work GitHub account and a personal one. One day a push fails with Permission to your-org/api.git denied to your-personal-name, or a private repository says Repository not found even though you can open it in the browser. Git sent the other account.
On Windows there are three common ways Git and GitHub pick an account: Git Credential Manager, the GitHub CLI (gh), and SSH keys. They work differently, and each one needs its own trick to follow the folder you are in. This post compares them and gives a working per-folder setup for each.
The short answer
Section titled “The short answer”Three separate things decide “who you are” on GitHub:
| What | Decided by | Check with |
|---|---|---|
| The name and email inside a commit | user.name and user.email in Git config |
git var GIT_AUTHOR_IDENT |
| The account that pushes over HTTPS | The credential helper (GCM, or gh) |
git remote -v, then the helper |
| The account that pushes over SSH | The SSH key that is offered | ssh -T git@github.com |
The account gh uses for API calls |
The active gh account |
gh auth status --active |
Fixing one does not fix the others. A correct email with the wrong push account is still a push from the wrong account.
First, look at the remote. It tells you which half applies:
git remote -vhttps://github.com/... means a credential helper decides. git@github.com:... means an SSH key decides.
Why GitHub cannot tell you apart
Section titled “Why GitHub cannot tell you apart”Over HTTPS, Git asks a credential helper for a login for github.com. By default the helper looks only at the host, not at the repository path. The Git docs say a credential stored for https://example.com/foo.git “will also be used for https://example.com/bar.git”. So one host, one saved login, unless you tell Git otherwise.
GitHub’s own errors are honest about this. “Permission to user/repo denied to other-user” means the account you pushed with “does not have access to the repository”. “Repository not found” appears when “the repository does not exist or you do not have permission to access it”, which for a private repository often just means the wrong account.
Option 1: Git Credential Manager
Section titled “Option 1: Git Credential Manager”Git for Windows ships Git Credential Manager (GCM). On Windows it keeps logins in Windows Credential Manager, which GCM’s docs call “the default store on Windows”.
GCM supports several accounts on one host, “with a bit of complexity”. Its docs give two ways to tell them apart.
Put the user name in the remote URL. “HTTPS URLs include an optional “name” part before an @ sign”, and GCM uses it to pick the login:
git remote set-url origin https://your-work-login@github.com/your-org/api.gitOr set a default user name in config. The docs show credential.<URL>.username. Combine it with a folder rule (see a different Git email per folder) and every repository in C:\Work asks GCM for the work login. In your .gitconfig-work:
[credential "https://github.com"] username = your-work-loginWe checked that Git resolves this value only inside the work folder. If the login contains @, the GCM docs say to write it as %40.
Good at: it is already installed, and it needs no extra tool. Watch out for: when GCM has no saved login for that user name yet, it asks you to sign in. Sign in with the matching account there, or the wrong login gets saved under the work name.
Option 2: the GitHub CLI
Section titled “Option 2: the GitHub CLI”gh has supported several accounts since v2.40.0. Its release notes list “adding multiple accounts for GitHub.com and GitHub Enterprise with gh auth login” and “switching manually between accounts for gh and git use with gh auth switch”.
gh auth login # run once per accountgh auth status # lists every account and marks the active onegh auth switch --user your-work-logingh auth switch “changes the authentication configuration that will be used when running commands targeting the specified GitHub host.” If you ran gh auth setup-git, which “configures git to use GitHub CLI as a credential helper”, Git pushes follow the active account too.
Good at: API work, pull requests, issues, and a quick switch. Watch out for: the active account is one setting for the whole PC. Two terminals in two folders cannot use two accounts at the same time, and you have to remember to switch back.
Two more facts worth knowing:
GH_TOKENandGITHUB_TOKEN“take precedence over previously stored credentials”. If one of them is set in your environment,ghignores the account you switched to.gh auth statusandgh auth tokenboth have options that print the token itself. You never need them to check who you are, so leave them alone.
Option 3: one SSH key per account
Section titled “Option 3: one SSH key per account”GitHub does not let two accounts share one SSH key. Its docs say the “Key already in use” error “occurs when you try to add a key that’s already been added to another account or repository”. So each account gets its own key. GitHub’s page on managing multiple accounts gives this form for one command:
GIT_SSH_COMMAND='ssh -i PATH/TO/KEY/FILE -o IdentitiesOnly=yes' git clone git@github.com:OWNER/REPOSITORYThat is shell syntax. On Windows, make it per folder instead with core.sshCommand, which takes “the same form as the GIT_SSH_COMMAND environment variable”. In your .gitconfig-work:
[core] sshCommand = ssh -i C:/Users/you/.ssh/id_ed25519_work -o IdentitiesOnly=yesUse forward slashes in the key path. IdentitiesOnly=yes matters: without it, ssh may offer other keys from the SSH agent first. The OpenSSH manual says the option makes ssh “only use the configured authentication identity and certificate files … even if ssh-agent(1) … offers more identities”.
GitHub’s docs also show the other classic setup, a host alias in ~/.ssh/config with its own IdentityFile and IdentitiesOnly yes. It works, but every remote must use the alias name instead of github.com.
Test a key with:
ssh -T git@github.comGitHub answers “Hi USERNAME! You’ve successfully authenticated, but GitHub does not provide shell access.” The user name tells you which account the key belongs to. To test one particular key, pass the same options that your core.sshCommand uses:
ssh -i C:/Users/you/.ssh/id_ed25519_work -o IdentitiesOnly=yes -T git@github.comGood at: fully per folder, no sign-in windows. Watch out for: it only applies to git@github.com: remotes. An HTTPS remote in the same folder still uses the credential helper. If your key has no access, see Permission denied (publickey).
Side by side
Section titled “Side by side”| Git Credential Manager | gh | SSH keys | |
|---|---|---|---|
| Remote type | HTTPS | HTTPS (as helper) and the API | SSH |
| Several accounts | Yes, by user name | Yes, since v2.40.0 | Yes, one key each |
| Per folder | Yes, with credential.<url>.username in a folder rule |
No, one active account | Yes, with core.sshCommand in a folder rule |
| Where the secret lives | Windows Credential Manager | System credential store, or a plain file if none | The key file in .ssh |
| Two folders at the same time | Yes | No | Yes |
How Devpit does the same thing
Section titled “How Devpit does the same thing”Devpit’s Accounts page shows GitHub as its own row, next to Git. The Git page has two lines: Commits as (name and email) and Pushes as (GitHub account). See Git and GitHub accounts.
- It uses
gh’s own accounts. You add an account withgh auth login, which is additive. Devpit never runsgh auth switch, so nothing global changes behind your back. ghfollows the folder. When you runghin a folder with a rule, a small Devpit shim starts the realghwith that account’s token for that one process. The token comes fromgh auth token --user <name>in memory and is never shown, saved or logged.- Pushes follow the folder. For
github.com, Devpit sets its own credential helper, which works out the folder (also duringgit clone, where it readsGIT_DIRbecause the working folder is still the parent). It is the onlygithub.comhelper while Devpit manages pushes. Git’s docs explain why that is possible: an emptyhelper =line “resets the helper list to empty”. For folders on your default account, it hands the request to the helper you had before, which Devpit records so undo can put it back. It never passes a work token to GCM to save. - SSH remotes follow the key, not the helper. The Git page says which one applies and offers a per-folder key with
core.sshCommandandIdentitiesOnly=yes. - Every change has a preview that defaults to No, and can be undone. Devpit stores no token of its own.
Checklist
Section titled “Checklist”- Run
git remote -vto see if HTTPS or SSH decides. - For HTTPS, give each account its own user name in GCM, per folder or per remote.
- For SSH, give each account its own key and set
core.sshCommandper folder withIdentitiesOnly=yes. - Use
gh auth switchonly if one account at a time is enough. - Make sure
GH_TOKENis not set ifghignores your switch. - Set the commit email separately.
Sources
Section titled “Sources”- Git: gitcredentials (helpers,
useHttpPath, empty helper) - Git: git-config,
core.sshCommand - Git Credential Manager: Multiple users
- Git Credential Manager: Credential stores
- GitHub CLI v2.40.0 release notes (multiple accounts)
- GitHub CLI manual: gh auth switch
- GitHub CLI manual: gh auth setup-git
- GitHub CLI manual: gh auth login (credential storage)
- GitHub CLI manual: environment variables
- GitHub Docs: Managing multiple accounts
- GitHub Docs: Testing your SSH connection
- GitHub Docs: Error: Key already in use
- GitHub Docs: Error: Permission to user/repo denied to other-user
- GitHub Docs: Troubleshooting cloning errors (Repository not found)
- OpenSSH: ssh_config (
IdentitiesOnly)
Common questions
Why does GitHub say Repository not found for a repo I can open in the browser?
GitHub shows that error when the repository does not exist or the account you are pushing with has no access to it. For a private repository, this usually means Git sent the credentials of your other account. Check which account the credential helper or SSH key belongs to.
Does gh auth switch change the account Git pushes with?
It changes the active gh account for that host. If you ran gh auth setup-git, Git asks gh for credentials, so pushes follow the active account too. It is one switch for the whole PC, not per folder.
Is user.email the same as the account I push with?
No. user.email is written into the commit. The push account is decided by the credential helper for HTTPS remotes or by the SSH key for SSH remotes. GitHub links commits to accounts by the email in the commit.
