There's a specific flavor of embarrassment that only developers know.
It's 11 PM. You've just finished a weekend project you're genuinely proud of. You push it to your personal GitHub, open the repo in your browser to admire it, and there it is at the top of the commit list:
developer@company.com committed 2 minutes ago
Your work email. On your personal project. Sitting in a public repo. Forever.
Nobody's going to fire you over it. But it looks sloppy, it quietly announces which company you work at to every stranger who reads your code, and — the part that actually stings — it means the commit doesn't show up on your personal contribution graph. All those little green squares you earned at midnight? They went to an account that doesn't even know they exist.
I did this for about two years before I fixed it. Here's the fix, and more importantly, here's every way I managed to get it wrong first.
Why this happens
Git has exactly one global identity, stored in ~/.gitconfig. When you set it up on day one at a new job, you type in your work email, and Git dutifully stamps that on every commit you make on that machine for the rest of time.
Git does not know the difference between ~/work/critical-production-service and ~/study/thing-i-made-at-2am. It's a version control system, not a mind reader. To Git, it's all just directories.
So we have to tell it.
Step 1: Teach Git to read the room
Git has a feature called conditional includes, and it is the single most underrated thing in the entire tool. It lets you say: "if the repo lives in this folder, use a different identity."
First, make a file for your personal identity. Call it ~/.gitconfig-personal:
[user]
name = Your Name
email = your.personal@gmail.com
Then, at the bottom of your existing ~/.gitconfig, add:
[includeIf "gitdir:~/study/"]
path = ~/.gitconfig-personal
Replace ~/study/ with wherever your personal projects live. Mine is ~/study/, because I started that folder to learn things and never renamed it.
Two details that will bite you if you skip them:
The trailing slash matters. gitdir:~/study/ means "this folder and everything inside it." Without the slash, Git gets picky in ways you don't want to debug at midnight.
It must go at the bottom. Git reads the config top to bottom, and the last value wins. If you paste the includeIf block above your [user] section, your work email will override the personal one and you'll spend twenty minutes convinced the feature is broken. It is not broken. You are just at the wrong altitude in the file. (Ask me how I know.)
Verify it worked
cd ~/study/any-project
git config user.email # should print your personal email
cd ~/work/any-project
git config user.email # should print your work email
If the personal folder still shows work email, check two things: is the includeIf at the bottom, and is that folder actually a Git repo? Conditional includes evaluate against a repository's location. Run it in a folder with no .git in it and Git shrugs and gives you the global default. This confused me for a solid ten minutes.
Step 2: The keys to two kingdoms
Identity is only half the problem. The other half is authentication — proving to GitHub that you're allowed to push.
Your laptop has one SSH key. GitHub has a rule: one key, one account. You cannot add the same public key to two different GitHub accounts. GitHub will look at it, recognize it, and tell you it's already in use, in the tone of a bouncer who remembers your face.
So: second key.
ssh-keygen -t ed25519 -C "your.personal@gmail.com" -f ~/.ssh/id_ed25519_personal
Note the -f flag. It gives the key a specific name instead of overwriting ~/.ssh/id_rsa. Do not skip this. Your existing key probably has access to production servers, deploy targets, and other things that are extremely annoying to re-provision because you were typing fast.
Copy the public half:
pbcopy < ~/.ssh/id_ed25519_personal.pub
Then go to GitHub → Settings → SSH and GPG keys → New SSH key, and paste it in. Make sure you're logged into your personal account. If you add your personal key to your work account, everything will appear to work until it very much doesn't.
Step 3: The alias that makes it all click
Here's the clever bit. You now have two keys, but when you run git push, SSH has no idea which one to use. It'll just offer them in order and hope.
So you invent a hostname that doesn't exist.
Add this to ~/.ssh/config:
Host github-personal
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_personal
IdentitiesOnly yes
Read that carefully, because it's doing something sneaky. github-personal isn't a real domain. It's a nickname. When you tell Git to connect to github-personal, SSH looks it up in this config, sees "oh, that means github.com, and use this specific key," and does the right thing.
IdentitiesOnly yes is the load-bearing line. Without it, SSH helpfully offers every key it knows about, starting with your work one. GitHub accepts the first valid key it sees, so you authenticate as the wrong account and get a confusing permission error about a repo you're literally staring at in your browser.
Now use the alias in your remote URL:
git remote add origin git@github-personal:yourusername/your-repo.git
Everything after the colon is normal. Only the host part changed.
Test it:
ssh -T git@github-personal
You want: Hi yourusername! You've successfully authenticated...
If it greets you by your work username, IdentitiesOnly is missing or misspelled.
The four errors you are about to hit
I hit all of these. In order. Consider this the walkthrough.
ssh: Could not resolve hostname github-personal
You used the alias before creating it. SSH looked for a real server called github-personal, found nothing, and gave up. Go back and add the Host block to ~/.ssh/config.
The reason this error is confusing is that it sounds like a network problem. It isn't. It's a "you invented a nickname and forgot to write it down" problem.
fatal: refusing to merge unrelated histories
You created the repo on GitHub with the "Add a README" checkbox ticked, so GitHub made a commit. Meanwhile you made your own first commit locally. Two separate histories, no common ancestor, and Git — reasonably — refuses to guess.
If the remote only contains GitHub's auto-generated stub:
git push -u origin main --force
If there's anything on the remote you actually care about:
git pull origin main --allow-unrelated-histories
...and then resolve the conflict like an adult. Check git log origin/main before you force anything. Force pushes are permanent, and "I thought it was empty" is not a recovery strategy.
remote: Permission to user/repo.git denied
Wrong key got offered. Either IdentitiesOnly yes is missing, or you added the public key to the wrong GitHub account.
The HTTPS trap
This one is the sneakiest, because nothing errors — it just silently does the wrong thing.
If your remote starts with https://github.com/... instead of git@..., none of your SSH setup applies. On macOS, Git pulls credentials from the Keychain, where your work account's token has been quietly living since your first day. It'll use that. Every time.
Check your remotes:
git remote -v
If you see https://, switch it:
git remote set-url origin git@github-personal:yourusername/your-repo.git
And if you need to evict the stored credential:
printf 'protocol=https\nhost=github.com\n\n' | git credential-osxkeychain erase
Was it worth it?
Fifteen minutes of setup. Then it just... works. Forever. Silently.
I clone a personal project into ~/study/, and it's me. I clone a work repo anywhere else, and it's work me. I have never once had to think about it since, which is the highest compliment you can pay to any piece of configuration.
The green squares go to the right account now. My work email isn't scattered across public repos. And when a recruiter opens my GitHub, they see a person with side projects — not a person who apparently does side projects on company time.
That last one wasn't even true. But it sure looked like it.
If this saved you from an awkward commit history, drop a heart. If you're reading this because you already pushed with the wrong email — git commit --amend --author="Name <email>" fixes the last one, and git rebase fixes the rest, but that's a whole other article and honestly, sometimes you just start a fresh repo and move on with your life.
Top comments (0)