Git Identity Crisis: Automating Multi-Account GitHub Like a Sane Person
Stop manually switching between your work and personal GitHub accounts like it's 2015
3-min read
I have two GitHub accounts. One for work, one for personal projects. If you’re reading this, you probably do too. And if you’re anything like me, you’ve been committing from the wrong email at least once a month, silently polluting your contribution graph with phantom identities
The problem is deceptively simple: when I git push for any of my various open source projects, I would like it routed through my personal account.
And when I push from work, it should use my work email. No manual switching. No “oh crap, wrong email” moments at 2am.
Here’s the setup I landed on. It took a couple minutes and I haven’t thought about it since.
Note: If you’re an SSH person, you can solve this with separate keys and ~/.ssh/config Host aliases but I use HTTPS across machines and prefer leaning on gh’s token management rather than juggling key pairs
The Commit Identity Problem
Git uses a global user.name and user.email from ~/.gitconfig for every commit. If your global config is your work email, every commit across every repo — including your weekend passion project — gets stamped with you@acme.com.
You could set a per-repo override with git config user.email in each project dir, but that’s fragile. You’ll forget (read: I have). You’ll clone a new repo and push three commits before realizing you’ve been committing as the wrong person.
The Fix: includeIf with Remote URL Matching
Git v2.36 introduced hasconfig:remote,1 which lets you conditionally include config files based on the remote URL. This is the key.
First, create a separate config file for your personal identity:
# ~/.gitconfig-personal
[user]
name = Your Name
email = you@gmail.comThen add conditional includes to your ~/.gitconfig:
[user]
name = Your Name
email = you@work.com
[includeIf “hasconfig:remote.*.url:https://github.com/YourPersonalUsername/**”]
path = ~/.gitconfig-personal
[includeIf “hasconfig:remote.*.url:git@github.com:YourPersonalUsername/**”]
path = ~/.gitconfig-personalThat’s it. Any repo with a remote pointing to your personal GitHub org automatically uses the personal identity. HTTPS and SSH both covered. No per-repo config, no directory-based hacks.
The Push / Pull Auth Problem
Solving the commit identity is only half the battle. When you git push, git also needs to authenticate with GitHub. If you use gh (the GitHub CLI), it has its own auth — and it only has one “active” account at a time.
The naive approach: gh auth switch before every push. The correct approach: a custom credential helper that routes automatically.
The Fix: A Custom Credential Helper
Git’s credential system supports custom helpers — scripts that receive the target host and repo path, and return the appropriate credentials. We can write one that checks the repo owner in the URL and picks the right `gh` token:
#!/bin/bash
# ~/.local/bin/gh-credential-switcher
if [ “$1” != “get” ]; then
exit 0
fi
host=”“
path=”“
while IFS=’=’ read -r key value; do
[ -z “$key” ] && break
case “$key” in host) host=”$value” ;; path) path=”$value” ;;
esac
done
if [[ “$host” != “github.com” ]]; then
exit 0
fi
if [[ “$path” == YourPersonalUsername/* ]]; then
user=”YourPersonalUsername”
else
user=”your-work-username”
fi
token=$(gh auth token --user “$user” 2>/dev/null)
if [ -n “$token” ]; then
echo “protocol=https”
echo “host=github.com”
echo “username=$user”
echo “password=$token”
fi Make it executable chmod +x) and wire it into your ~/.gitconfig:
[credential “https://github.com”]
helper =
helper = !/path/to/gh-credential-switcher
useHttpPath = trueThe empty helper = line clears any previously registered credential helpers (looking at you, macOS Keychain). And useHttpPath = true is critical — without it, git only sends the host to credential helpers, not the repo path, and the script can’t distinguish between orgs.
The macOS Gotcha
If you’re on a Mac, Xcode ships a system-level gitconfig at /Applications/Xcode.app/Contents/Developer/usr/share/git-core/gitconfig that registers osxkeychain as a credential helper. This runs before your custom helper and returns whatever cached credential it has — defeating the entire setup.
The helper = line in [credential “https://github.com”] clears this. If it doesn’t stick (system-level configs can be stubborn), you can also add a global [credential] block:
[credential]
helper =
helper = !/path/to/gh-credential-switcherPrerequisites
Both GitHub accounts need to be logged into gh:
gh auth login # login with your work account
gh auth login # login with your personal accountYou can verify both are available with
gh auth statusThe “active” account doesn’t matter anymore — the credential helper bypasses it entirely.
Verification
Quick sanity check across repos:
# Personal repo
$ git -C ~/projects/side-project config user.email
you@gmail.com
$ git -C ~/projects/side-project ls-remote --heads origin
a1b2c3d refs/heads/main# Work repo
$ git -C ~/projects/work-thing config user.email
you@work.com
$ git -C ~/projects/work-thing ls-remote --heads origin
d4e5f6a refs/heads/mainDifferent identities, different auth tokens, zero manual switching.
TL;DR
Layer
Mechanism
Config
Commit identity
includeIf hasconfig:remote
~/.gitconfig+~/.gitconfig-personal
Push / pull auth
Custom credential helper
~/.local/bin/gh-credential-switcher
macOS Keychain bypass
helper =(clear line)~/.gitconfig
Path-based routing
useHttpPath = true~/.gitconfig
Clone any repo and it just works. New personal project? Personal identity and auth. New work repo? Work credentials. The setup is entirely URL-based, so it doesn’t matter where on disk the repo lives or what branch you’re on.
Ten minutes of config. Months of not thinking about it.
Introduced in Git 2.36, see docs: https://git-scm.com/docs/git-config#Documentation/git-config.txt-hasconfigremoteurl

