2026-01-10 - How I Setup Multiple GitHub Accounts on My Laptop
tl;dr: Use separate SSH keys for authentication and signing, configure SSH hosts with different names, and leverage Git’s conditional config to automatically switch between accounts based on directory.
The Problem
I have two GitHub accounts - let’s call them me (personal) and work (company). I want to:
- Use my personal account (
me) for all repos on my laptop by default - Use my work account (
work) exclusively for repos inside~/Code/jw/(my company folder) - Set up SSH keys for both authentication AND commit signing
- Have Git automatically use the correct identity based on which folder I’m in
No manual switching, no mistakes, no accidentally committing with the wrong email.
The Solution
The setup involves three main steps:
- Generate SSH keys for both accounts (authentication + signing)
- Configure SSH to use different keys based on hostname
- Configure Git to use different identities based on directory
Let’s walk through each step.
Step 1: Generate SSH Keys
We need four keys total: two for authentication (one per account) and two for signing commits (one per account).
Run these commands to generate all four keys:
# Personal account - authentication
ssh-keygen -t ed25519 -C "hello@hungdoan.xyz" -f ~/.ssh/github_id_me
# Work account - authentication
ssh-keygen -t ed25519 -C "hung@jw.com" -f ~/.ssh/github_id_work
# Personal account - signing
ssh-keygen -t ed25519 -C "hello@hungdoan.xyz" -f ~/.ssh/github_sign_me
# Work account - signing
ssh-keygen -t ed25519 -C "hung@jw.com" -f ~/.ssh/github_sign_work
You’ll be prompted to enter a passphrase for each key. Use a strong passphrase (or the same one for convenience - your choice).
After running these commands, you should have 8 files in ~/.ssh/:
github_id_me github_id_me.pub
github_id_work github_id_work.pub
github_sign_me github_sign_me.pub
github_sign_work github_sign_work.pub
The .pub files are your public keys (safe to share), and the files without extensions are your private keys (keep them secret!).
Step 2: Configure SSH
Now we need to tell SSH which key to use for which GitHub account. The trick is to use different host aliases.
Open (or create) ~/.ssh/config:
open ~/.ssh/config
Add the following configuration:
# Personal account (default)
Host github.com
HostName github.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/github_id_me
IdentitiesOnly yes
# Work account (use github.com-work as host)
Host github.com-work
HostName github.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/github_id_work
IdentitiesOnly yes
How This Works
- When you use
git@github.com:..., SSH uses your personal key (github_id_me) - When you use
git@github.com-work:..., SSH uses your work key (github_id_work)
The IdentitiesOnly yes setting ensures SSH only tries the specified key, not all keys in your ~/.ssh/ folder.
Step 3: Add Public Keys to GitHub
Now we need to upload the public keys to GitHub.
For Your Personal Account
- Go to https://github.com/settings/keys
- Click “New SSH key”
- Choose “Authentication Key” as the key type
- Paste the content of your public key:
pbcopy < ~/.ssh/github_id_me.pub
- Click “Add SSH key”
- Repeat the process for the signing key:
- Choose “Signing Key” as the key type
- Paste the content of:
pbcopy < ~/.ssh/github_sign_me.pub
For Your Work Account
Repeat the same process, but:
- Log in to your work GitHub account
- Upload
github_id_work.pubas an Authentication Key - Upload
github_sign_work.pubas a Signing Key
Step 4: Configure Git
Now we need to tell Git which identity (name, email, signing key) to use based on the directory.
Main Git Config
Open your main Git config:
open ~/.gitconfig
Add this configuration:
# Load the default config for ALL repositories
[include]
path = ~/.gitconfig-me
# Override with work config for repos inside ~/Code/jw/
[includeIf "gitdir:~/Code/jw/"]
path = ~/.gitconfig-work
# SSH signing configuration (shared by both accounts)
[gpg]
format = ssh
[gpg "ssh"]
allowedSignersFile = ~/.ssh/allowed_signers
This tells Git:
- Use
~/.gitconfig-meas the default for all repos - If the repo is inside
~/Code/jw/, override with~/.gitconfig-work - Use SSH for GPG signing and reference the allowed signers file
Now create the allowed signers file (we’ll populate it later if you want local verification):
touch ~/.ssh/allowed_signers
Personal Account Config
Create ~/.gitconfig-me:
touch ~/.gitconfig-me
open ~/.gitconfig-me
Add your personal identity and signing configuration:
[user]
name = Hung Doan
email = hello@hungdoan.xyz
signingkey = ~/.ssh/github_sign_me.pub
[commit]
gpgSign = true
[tag]
gpgSign = true
[pull]
ff = true
Work Account Config
Create ~/.gitconfig-work:
touch ~/.gitconfig-work
open ~/.gitconfig-work
Add your work identity and signing configuration:
[user]
name = Hung Doan
email = hung@jw.com
signingkey = ~/.ssh/github_sign_work.pub
[commit]
gpgSign = true
[tag]
gpgSign = true
[pull]
ff = true
Note: You can use a different name for your work account if needed (I kept it the same).
Step 5: Test Your Setup
Let’s verify everything works correctly.
Test Personal Account
Clone a private repo from your personal account (anywhere outside ~/Code/jw/):
cd ~/Code
git clone git@github.com:your-username/your-private-repo.git
cd your-private-repo
Verify your identity:
git config user.email
# Should output: hello@hungdoan.xyz
git config user.name
# Should output: Hung Doan
Test Work Account
Clone a private repo from your work account (inside ~/Code/jw/):
cd ~/Code/jw
git clone git@github.com-work:company/work-repo.git
cd work-repo
Verify your identity:
git config user.email
# Should output: hung@jw.com
git config user.name
# Should output: Hung Doan (or whatever you set)
Notice we used git@github.com-work:... instead of git@github.com:.... This tells SSH to use the work key.
Important: Cloning Work Repos
When cloning work repos, you need to modify the clone URL to use the github.com-work host:
# GitHub gives you this URL:
git clone git@github.com:company/repo.git
# Change it to:
git clone git@github.com-work:company/repo.git
Alternatively, after cloning with the default URL, update the remote:
git remote set-url origin git@github.com-work:company/repo.git
Verifying Commit Signing
Quick Test on GitHub
The easiest way to verify commit signing is to create an empty repo on GitHub and push a test commit:
# Create a new repo on GitHub, then:
mkdir test-signing
cd test-signing
git init
echo "test" > README.md
git add README.md
git commit -m "Test commit signing"
git remote add origin git@github.com:your-username/test-signing.git
git push -u origin main
Check the commit on GitHub - it should show a “Verified” badge next to it.
Verifying Locally (Optional)
If you want to verify signed commits locally with git log --show-signature, you need to populate the allowed_signers file we created earlier.
Without it, running:
git log --show-signature -1
Will show this error:
error: gpg.ssh.allowedSignersFile needs to be configured and exist for ssh signature verification
To enable local verification, add your signing keys to ~/.ssh/allowed_signers:
open ~/.ssh/allowed_signers
1. Copy your personal signing key:
pbcopy < ~/.ssh/github_sign_me.pub
2. Paste it into the file, but move the email to the beginning
The public key format is:
ssh-ed25519 AAAA... hello@hungdoan.xyz
But the allowed_signers format requires the email first:
hello@hungdoan.xyz ssh-ed25519 AAAA...
3. Repeat for your work signing key:
pbcopy < ~/.ssh/github_sign_work.pub
Your final ~/.ssh/allowed_signers file should look like:
hello@hungdoan.xyz ssh-ed25519 AAAA...
hung@jw.com ssh-ed25519 BBBB...
4. Test it:
git log --show-signature -1
You should now see:
Good "git" signature for hello@hungdoan.xyz with ED25519 key SHA256:...
Success! Git can now verify your signed commits locally.
Troubleshooting
Permission Denied (publickey)
If you get this error when cloning:
Permission denied (publickey).
fatal: Could not read from remote repository.
Check:
- Did you add the public key to GitHub?
- Are you using the correct host (
github.comvsgithub.com-work)? - Test your SSH connection:
ssh -T git@github.com
ssh -T git@github.com-work
Wrong Email in Commits
If commits show the wrong email:
- Check which config is being used:
git config --show-origin user.email
- Verify the
[includeIf]path in~/.gitconfigmatches your directory structure - Make sure you’re inside the correct directory (
~/Code/jw/for work)
Commits Not Signed
If commits aren’t being signed:
- Verify signing is enabled:
git config commit.gpgsign
# Should output: true
- Check the signing key path:
git config user.signingkey
# Should output: ~/.ssh/github_sign_me.pub (or work variant)
- Verify GPG format is set to SSH:
git config gpg.format
# Should output: ssh
Bonus: GitLens Configuration for VSCode/Cursor
If you use VSCode, Cursor, or any editor with GitLens, you’ll notice that links to github.com-work repos won’t work correctly in the GitLens interface. GitLens doesn’t recognize github.com-work as a valid GitHub domain.
To fix this, add a custom remote configuration to your workspace settings.
Create or update .vscode/settings.json in your work project:
{
"gitlens.remotes": [
{
"domain": "github.com-work",
"type": "Custom",
"name": "jw",
"protocol": "https",
"urls": {
"repository": "https://github.com/${repo}",
"branches": "https://github.com/${repo}/branches",
"branch": "https://github.com/${repo}/commits/${branch}",
"commit": "https://github.com/${repo}/commit/${id}",
"file": "https://github.com/${repo}?path=${file}${line}",
"fileInBranch": "https://github.com/${repo}/blob/${branch}/${file}${line}",
"fileInCommit": "https://github.com/${repo}/blob/${id}/${file}${line}",
"fileLine": "#L${line}",
"fileRange": "#L${start}-L${end}"
}
}
]
}
This tells GitLens to map the github.com-work domain to the actual GitHub URLs, so all the “Open on GitHub” links and integrations work correctly.
Key Takeaways
- Separate keys for auth and signing - While you could use the same key for both, separating them is a security best practice
- SSH host aliases - Using
github.com-workas an alias lets you route to different keys without changing GitHub’s actual hostname - Conditional Git config - The
[includeIf "gitdir:..."]directive is powerful for automatically switching identities - Remember to modify clone URLs - For work repos, use
git@github.com-work:...instead ofgit@github.com:... - GitLens custom remotes - Configure GitLens to recognize your custom SSH host for seamless editor integration
This setup has saved me countless times from accidentally committing with the wrong account. Set it once, forget about it, and let Git handle the rest!
Environment:
- macOS 14.5
- Git 2.39+
- OpenSSH 9.0+
References: