Two GitHub Profiles, One Laptop: The Pragmatic Guide
Two accounts, one laptop, zero context-switching headaches.
This post is about how I fixed that mess — not by chasing fancy abstractions, but by making Git and SSH play nicely together with some pragmatic plumbing.
The Problem
On paper, it sounds simple:
Company GitHub account → already set up with an SSH key (~/.ssh/id_rsa), global Git config uses tushar@work.com.
Personal GitHub account → I want a new SSH key, repos under a dedicated folder (~/tushar/), and commits showing my personal email.
In reality, Git doesn’t make it that easy:
Identity bleed: Git’s user.name and user.email are global by default. If you don’t override them, your work email leaks into personal repos.
SSH collisions: By default, GitHub only has one hostname: github.com. Which key it uses depends on your SSH config. Without care, everything routes through your company identity.
Muscle memory: You don’t want to remember special clone commands. You want git clone to just work.
Implementation
I didn’t want a brittle workflow where I manually swap configs or run custom scripts. The goal was event-driven identity switching — Git should know which account to use simply based on where I’m working.
Here’s how I wired it up:
1. Two SSH Keys, Two Hosts
I generated a second SSH key for my personal account:
ssh-keygen -t ed25519 -C "me@gmail.com" -f ~/.ssh/id_rsa_personalThen I taught SSH to treat GitHub as two different hosts:
vi ~/.ssh/config# Default: Company
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa
IdentitiesOnly yes
# Personal
Host github-personal
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa_personal
IdentitiesOnly yesNow I can talk to GitHub through github.com (work) or github-personal (personal).
2. Directory-Based Git Config
Next problem: user.email. I wanted anything in ~/tushar/ to use my personal identity. Luckily, Git has an underrated feature called includeIf.
In ~/.gitconfig:
[user]
name = Work User
email = work@company.com
[includeIf "gitdir:/Users/tusharkhanka/tushar/**"]
path = /Users/tusharkhanka/.gitconfig-personalAnd then in ~/.gitconfig-personal:
[user]
name = Tushar Khanka
email = me@gmail.com
[url "git@github-personal:"]
insteadOf = git@github.com:This does two things at once:
Inside ~/tushar/*, Git rewrites my identity to personal.
Any git@github.com:... URL in that path is transparently rewritten to git@github-personal:..., so SSH uses the right key.
3. Testing Reality
Here’s the catch I stumbled on: includeIf only applies inside a real repo. Running git config user.email in ~/tushar/ will still show your global identity. That confused me for a while.
But once I cd’d into a real repo under ~/tushar/* and checked:
git config user.email
git config --show-origin user.emailI finally saw:
me@gmail.com
file:/Users/tusharkhanka/.gitconfig-personalThat was the “aha” moment.
Results
With this setup:
Work repos under ~/workspace/* → automatically use my company email + company SSH key.
Personal repos under ~/tushar/* → automatically use my personal email + personal SSH key.
Cloning is seamless:
Work: git clone git@github.com:CompanyOrg/repo.git
Personal: git clone git@github.com:MyUser/repo.git (rewritten under the hood).
No more manual switching, no more accidents where a side project commit shows up with my company identity.
Lessons Learned
Git’s config system is powerful but picky.
gitdir:~/tushar/ doesn’t work, because ~ won’t expand.
You need the absolute path, and often /** to catch subdirectories.
SSH aliases are your friend.
GitHub only has github.com, but nothing stops you from inventing github-personal or github-sideprojects to force key separation.
Don’t test in empty directories.
includeIf only evaluates inside real repos. Test from within a .git directory, otherwise you’ll chase ghosts.
Pragmatism beats clever scripts.
I first wrote a shell script to rewrite remotes, but the config approach was cleaner, automatic, and future-proof.
Conclusion
This wasn’t about elegance; it was about pragmatism. I wanted to prevent identity bleed between work and personal projects without adding cognitive overhead. The end result is boring in the best way: I don’t think about it anymore.
Scaling infrastructure often works the same way. You don’t need a silver bullet; you need guardrails that let you move fast without tripping yourself up. Git’s includeIf and SSH’s Host blocks gave me exactly that.
Now when I hack on a side project over the weekend, I know the commits belong to me, not my employer. That’s the kind of separation that keeps both sides happy.
TL;DR — Copy-Paste Setup
If you just want the working config, here it is:
~/.ssh/config
# Work (default)
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa
IdentitiesOnly yes
# Personal
Host github-personal
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa_personal
IdentitiesOnly yes~/.gitconfig
[user]
name = Work User
email = work@company.com
[includeIf "gitdir:/Users/yourusername/tushar/**"]
path = /Users/yourusername/.gitconfig-personal~/.gitconfig-personal
[user]
name = Your Name
email = your@email.com
[url "git@github-personal:"]
insteadOf = git@github.com:Usage
Clone work repos normally:
git clone git@github.com:CompanyOrg/repo.gitClone personal repos the same way (Git rewrites it for you):
git clone git@github.com:MyUser/repo.git

