The short answer
Give each account its own SSH key and add each public key to its GitHub account. Make work repos push with the work key by setting core.sshCommand to ssh -i ~/.ssh/id_work -o IdentitiesOnly=yes for them, and set the commit email per folder with an includeIf "gitdir:~/work/" block in ~/.gitconfig. Log the GitHub CLI into both accounts with gh auth login and move between them with gh auth switch. Then check any repo with git config --show-origin --get user.email.
On this page
Why one Mac mixes up two accounts
GitHub doesn't know which of your accounts you meant. It reads two separate things: the SSH key or HTTPS login you push with decides which account is allowed to push, and the email inside each commit decides whose profile the commit is linked to. The GitHub CLI and commit signing add two more. Each comes from a different place on your Mac:
| Setting | Where it comes from | What goes wrong |
|---|---|---|
| Commit name and email | user.name and user.email, from the repo's .git/config, an includeIf rule or ~/.gitconfig | Work commits made with your personal email, linked to the wrong profile |
| Push credentials | The SSH key ~/.ssh/config or core.sshCommand picks, or an HTTPS login in the Keychain | “Permission denied” or “Repository not found” when the key belongs to the other account |
| GitHub CLI | The active gh account for github.com, one for every terminal at once | Pull requests and issues opened from the wrong account |
| Signing key | user.signingkey, gpg.format and commit.gpgsign | Work commits signed with your personal key, shown as Unverified |
Commit name and email
- Where it comes from
user.nameanduser.email, from the repo's.git/config, anincludeIfrule or~/.gitconfig- What goes wrong
- Work commits made with your personal email, linked to the wrong profile
Push credentials
- Where it comes from
- The SSH key
~/.ssh/configorcore.sshCommandpicks, or an HTTPS login in the Keychain - What goes wrong
- “Permission denied” or “Repository not found” when the key belongs to the other account
GitHub CLI
- Where it comes from
- The active
ghaccount for github.com, one for every terminal at once - What goes wrong
- Pull requests and issues opened from the wrong account
Signing key
- Where it comes from
user.signingkey,gpg.formatandcommit.gpgsign- What goes wrong
- Work commits signed with your personal key, shown as Unverified
Step 1: one SSH key per account
GitHub won't attach the same key to two accounts, so each account needs its own. Create one for each, with the account's email as a comment:
ssh-keygen -t ed25519 -C "sam@acme.dev" -f ~/.ssh/id_work
ssh-keygen -t ed25519 -C "samdev@example.com" -f ~/.ssh/id_personalCopy each public key with pbcopy < ~/.ssh/id_work.pub and add it on GitHub under Settings → SSH and GPG keys, signed in as the matching account. Then test each key on its own. GitHub answers with the account the key belongs to:
ssh -T -i ~/.ssh/id_work -o IdentitiesOnly=yes git@github.comGitHub replies with a greeting that names the account, such as “Hi sam-acme”, and closes the connection. If it names the other account, the key is attached to the wrong one.
Step 2: make each repo push with the right key
By default, ssh offers every key it knows to github.com and GitHub accepts the first one that matches any account. That's how a personal repo ends up pushing as work. There are two ways to pin the key.
With `core.sshCommand`. Git runs this command instead of plain ssh, so the repo always uses the key you name and remote URLs stay the normal git@github.com: form. IdentitiesOnly=yes stops ssh from offering other keys first. Set it for one repo, or put it in the work folder's file in step 3 so every work repo gets it:
git config core.sshCommand "ssh -i ~/.ssh/id_work -o IdentitiesOnly=yes"With a host alias in `~/.ssh/config`. This works for any tool that runs ssh, but every work remote has to use the alias instead of github.com:
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/id_work
IdentitiesOnly yesgit remote set-url origin git@github-work:acme-corp/billing-api.gitStep 3: the right commit email in each folder
Keep work repos in one folder, such as ~/work/, and let Git switch the email for everything inside it. Your global config keeps the personal identity, and an includeIf block loads a second file for the work folder:
[user]
name = Sam Lee
email = samdev@example.com
[includeIf "gitdir:~/work/"]
path = ~/.gitconfig-work[user]
email = sam@acme.dev
[core]
sshCommand = ssh -i ~/.ssh/id_work -o IdentitiesOnly=yesThe includeIf block has to come after the [user] section, because the last value Git reads wins. The trailing slash in gitdir:~/work/ makes the rule match every repo under that folder. If your work repos are spread around, Git 2.36 and later can match on the remote instead: includeIf "hasconfig:remote.*.url:git@github.com:acme-corp/**".
Step 4: both accounts in the GitHub CLI
Since version 2.40, gh can stay logged in to more than one account on github.com. Run gh auth login once for each account; the one you logged in to last becomes active. gh auth status lists them, and gh auth switch changes the active one:
gh auth login
gh auth status
gh auth switch --hostname github.com --user sam-acmeCheck what a repo will use
Inside any repo, these four commands show the identity it will commit and push as, and where each value comes from:
git config --show-origin --get user.email
git config --show-origin --get core.sshCommand
git remote -v
gh auth statusfile:/Users/sam/.gitconfig-work sam@acme.devIf core.sshCommand prints nothing, the key comes from ~/.ssh/config: ssh -G github.com | grep -i '^identityfile' lists the keys ssh will try for that host, in order. For signing, git config --show-origin --get user.signingkey shows the key and the file that sets it.
The faster way: Git identity map in iKnowMyMac
iKnowMyMac's Git screen runs these checks for every repo in your project folders at once. Who am I here? lists each repo with the email it commits as and the file and line that sets it, the key or login it pushes with, the GitHub CLI account and the signing key, and names each mismatch in a sentence. It reads Git and SSH settings only, never what's in your repos.