Multiple Git Users

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.