How to Keep Work and Personal Git Identities Separate on One Laptop #
Remote work erased the boundary between office machines and home machines. One laptop, two GitHub accounts, zero margin for error — until you push a Saturday side project and your work avatar appears on the commit. If you’ve ever scrambled to amend a commit after realizing git config --global user.email pointed at you@company.com the whole time, this guide is for you.
The fix isn’t remembering to override flags on every git commit. The fix is making Git choose the right identity automatically based on which folder you’re in. Here’s the full setup: SSH keys, SSH config, and Git’s includeIf directive.
Why Global Config Alone Is a Trap #
Git reads configuration in a cascade: system -> global -> local. A value in ~/.gitconfig (global) wins over /etc/gitconfig (system), but any value inside a repo’s .git/config (local) overrides both. Most developers set one global name and email and never think about it again — until they have two accounts.
| Scope | File | When it applies |
|---|---|---|
| System | /etc/gitconfig |
Every user on the machine |
| Global | ~/.gitconfig |
You, everywhere |
| Local | <repo>/.git/config |
One repository only |
The problem: global is too broad and local is too narrow. You want something in between — a rule that says “everything under ~/work/ is me-at-work, everything under ~/personal/ is me-at-home.” That’s exactly what includeIf provides.
Folder Convention #
Pick two root directories and stick to them:
~/work/ -> all company repositories
~/personal/ -> all personal / open-source repositoriesEvery repo you clone lands in one or the other. The rest of this guide assumes this split.
Step 1 — Generate SSH Keys for Each Account #
Create one ED25519 key per GitHub/GitLab identity:
# Work key
ssh-keygen -t ed25519 -C "you@company.com" -f ~/.ssh/id_ed25519_work
# Personal key
ssh-keygen -t ed25519 -C "you@personal.com" -f ~/.ssh/id_ed25519_personalAdd both public keys to their respective GitHub/GitLab accounts under Settings -> SSH and GPG keys. If you were using a Personal Access Token (PAT) before, switch to SSH — it avoids token expiry headaches entirely.
Load Keys into the SSH Agent #
ssh-add ~/.ssh/id_ed25519_work
ssh-add ~/.ssh/id_ed25519_personal
# Verify both are loaded
ssh-add -lYou should see two ED25519 entries, one per identity file.
Step 2 — Configure SSH Host Aliases #
Edit ~/.ssh/config so Git knows which key to offer for which remote:
# ~/.ssh/config
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_work
Host github-personal
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_personalIf you also use GitLab at work, add a matching block with HostName gitlab.com.
Clone with the Alias #
Instead of the real hostname, use the alias:
# Work repo
git clone git@github-work:company/project-api.git
# Personal repo
git clone git@github-personal:yourname/side-project.gitThe SSH alias routes each connection through the correct key — no guessing, no -i flag every time.
Step 3 — Set Up includeIf in .gitconfig #
Here’s the piece that eliminates the wrong-identity problem. Open ~/.gitconfig and add includeIf directives:
# ~/.gitconfig
[includeIf "gitdir:~/work/"]
path = ~/.gitconfig-work
[includeIf "gitdir:~/personal/"]
path = ~/.gitconfig-personalNow create each identity file:
# ~/.gitconfig-work
[user]
name = Your Name
email = you@company.com# ~/.gitconfig-personal
[user]
name = Your Name
email = you@personal.comHow it works: whenever Git runs inside a repo whose path matches gitdir:~/work/**, it reads ~/.gitconfig-work on top of the global config, overriding the user.name and user.email. The same logic applies to ~/personal/.
Tip: You can also set repo-specific config in a local file, but
includeIfsaves you from repeatinggit config user.emailon every fresh clone.
Step 4 — Verify Before You Commit #
Never trust — verify. Inside any repository:
# Quick check
git config user.email
git config user.name
# Full local config dump
git config --list --localIf the email doesn’t match the account you intend, stop — you’re either in the wrong directory or the includeIf pattern isn’t matching. Move the repo or fix the pattern before committing.
Quick Sanity Script #
Drop this one-liner into your shell prompt or a pre-commit hook if you want belt-and-suspenders safety:
git config user.email | grep -q "company.com" && echo "🔒 Work identity" || echo "🏠 Personal identity"Common Pitfalls #
| Pitfall | Fix |
|---|---|
| Commits still show wrong email | Verify the repo path matches the gitdir: pattern (trailing slash matters) |
| SSH prompts for passphrase every push | Run ssh-add (or use ~/.ssh/config with AddKeysToAgent yes) |
includeIf ignored on older Git |
Requires Git >= 2.13; upgrade with git --version |
| Already cloned with default URL | Change the remote: git remote set-url origin git@github-work:company/repo.git |
FAQ #
Can I have more than two profiles? #
Yes. Add more includeIf entries — one per directory (e.g., ~/oss/ for open-source contributions with a separate email). Each gets its own ~/.gitconfig-<label> file.
What if I forget to clone with the SSH alias? #
The default git@github.com: URL uses your default SSH key, which may be the wrong one. Always clone with the alias (github-work / github-personal), or — if you already cloned — fix the remote with git remote set-url.
Does includeIf work with GIT_DIR or worktrees? #
includeIf "gitdir:" matches against the working-directory path, so worktrees and GIT_DIR setups may behave differently. Test with git config user.email after setup.
Do I need separate GPG signing keys per profile? #
Not required, but recommended if your company enforces commit signing. Generate a GPG key per identity, add it to the corresponding gitconfig-<label> file under [user] signingkey, and set [commit] gpgSign = true.
Will this work on Windows? #
Yes, with minor path adjustments. Use gitdir:C:/Users/you/work/ (forward slashes) in includeIf. SSH config and key generation are identical under Git Bash or WSL.
Summary #
| Piece | What it does |
|---|---|
| Two SSH keys | Proves your identity to two different GitHub/GitLab accounts |
~/.ssh/config Host aliases |
Routes each connection to the right key |
includeIf in ~/.gitconfig |
Sets name/email per directory automatically |
Folder convention (~/work/, ~/personal/) |
Gives includeIf a path to match on |
Set it up once, and Git picks the right identity for every commit — no mental overhead, no more embarrassed post-push amendments.