If you work on multiple different projects on the same machine, you might run into an issue if the projects use different git identities, e.g., different work/personal/school accounts.
This is a short write-up on how to use a different identity for every repo under a given directory - without having to set git config user.email ... manually.
To solve this we use git's built-in conditional includes (includeIf).
How it works
~/.gitconfig is loaded for every repo. A conditional include pulls in a second config file only when the repo's .git directory lives under a path you specify. The later config's values override the previously loaded ones.
~/.gitconfig
│
├── [user] global-name / global@example.com # used everywhere by default
└── includeIf "gitdir:~/personal/"
└── ~/.gitconfig-personal # only applied to repos under ~/personal/
└── [user] personal-name / personal@example.com
Setup
Step 1 - create the per-folder config
~/.gitconfig-personal:
[user]
name = personal-name
email = personal@example.com
You can also put signingkey, a different [commit] block, [core] options, etc. here - anything that normally lives in ~/.gitconfig.
Step 2 - add the include to ~/.gitconfig
Append (order matters - keep this after the global [user] block):
[includeIf "gitdir:~/personal/"]
path = ~/.gitconfig-personal
Trailing slash matters. It matches every repo whose .git directory lives
anywhere under ~/personal/.
Step 3 - verify
From inside any repo under ~/personal/:
git config --show-origin user.email
# file:/Users/you/.gitconfig-personal personal@example.com
From a repo outside that folder, you should still see the global value.
Step 4 (optional) - clean up existing per-repo overrides
If you previously ran git config user.email ... inside each personal repo, those local values still win over the include. Unset them so the include takes effect:
find ~/personal -name .git -type d | while read gitdir; do
repo="${gitdir%/.git}"
git -C "$repo" config --local --unset user.name 2>/dev/null
git -C "$repo" config --local --unset user.email 2>/dev/null
done
Re-check a repo with git config --show-origin user.email - the origin
should now be ~/.gitconfig-personal, not .git/config.
What this does and does not cover
| Concern | Handled by includeIf? |
|---|---|
| Commit author name/email shown on commits | ✅ yes |
| GPG/SSH commit signing key | ✅ yes (put in include) |
| Push authentication to the remote | ❌ no |
user.name/user.email only affect how commits are labelled. Whether a push succeeds, and under which account, depends on the credential git hands to the remote:
- SSH remote (git@host:...) - the SSH key matched by ~/.ssh/config
- HTTPS remote (https://host/...) - the token stored in macOS Keychain (or whatever credential.helper resolves)
How to fix the same-host conflict (e.g., both accounts live on github.com)
macOS Keychain stores one token per host by default. If both your work and personal remotes are https://github.com/..., they share the same stored credential - whichever was saved last wins, and you'll push work commits under your personal token (or vice versa).
To fix this it is recommended to use SSH with host aliases:
Give each account its own SSH key and invent fake hostnames in ~/.ssh/config:
Host github-personal
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_personal
IdentitiesOnly yes
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_work
IdentitiesOnly yes
Then clone (or rewrite remotes) using the alias:
git clone git@github-personal:your-handle/repo.git
# or for an existing repo:
git remote set-url origin git@github-work:your-org/repo.git
No keychain collision because the SSH key fully determines the account.