Git Multi-Identity via Conditional Includes
- Context: Two GitHub accounts (personal + EMU) already authenticated via SSH host aliases; need per-account
user.nameanduser.emailwithout manual switching
Problem Statement¶
With SSH-based multi-account authentication in place, repositories are already routed to the correct GitHub account at the transport layer. However, Git commits still carry whichever user.name and user.email is set globally — meaning commits to EMU repositories show the personal identity (or vice versa) unless manually overridden per repository.
Goal: Automatically apply the correct author identity based on which account a repository belongs to, with zero per-repo configuration.
Solution (Implemented)¶
Use Git's includeIf directive with hasconfig:remote.*.url matching (available since Git 2.36) to conditionally load an identity file when a repository's remote URL matches an EMU organisation.
1. Create identity config file¶
~/.gitconfig-foo-org:
[user]
name = <FOO_ORG display name>
email = <FOO_ORG email address>
2. Add conditional includes to ~/.gitconfig¶
One includeIf rule per organisation:
[user]
name = <personal display name>
email = <personal noreply address>
[includeIf "hasconfig:remote.*.url:git@github.com:FOO_ORG/**"]
path = ~/.gitconfig-foo-org
[includeIf "hasconfig:remote.*.url:git@github.com:ANOTHER_FOO_ORG/**"]
path = ~/.gitconfig-foo-org
The insteadOf URL rewrites and includeIf rules are independent — place them in whichever order is readable:
[url "git@github-foo-org:FOO_ORG/"]
insteadOf = https://github.com/FOO_ORG/
insteadOf = git@github.com:FOO_ORG/
[url "git@github-foo-org:ANOTHER_FOO_ORG/"]
insteadOf = https://github.com/ANOTHER_FOO_ORG/
insteadOf = git@github.com:ANOTHER_FOO_ORG/
Critical: Pattern Must Match the Stored URL¶
hasconfig:remote.*.url matches against the remote URL as stored in .git/config, regardless of any url.<base>.insteadOf rewrites. The insteadOf rewriting happens at transport time only and does not affect conditional include evaluation.
This means:
- Correct:
git@github.com:FOO_ORG/**— matches the URL the user originally configured as the remote - Wrong:
git@github-foo-org:**— the host alias only exists after rewriting; it never appears in.git/config - Wrong:
git@github.com:FOO_ORG/:**— the extra colon before**is a literal character that will never match
Organisations Without URL Rewriting¶
Some organisations may authenticate fine with the default SSH key (e.g. because the personal account has access) but still need the EMU author identity on commits. These only require an includeIf rule — no insteadOf rewrite:
[includeIf "hasconfig:remote.*.url:git@github.com:SHARED_ORG/**"]
path = ~/.gitconfig-foo-org
3. Verification¶
# In a personal repo
git config user.email
# → <personal noreply address>
# In a FOO_ORG repo (with insteadOf rewrite)
git config user.email
# → <FOO_ORG email address>
# In a SHARED_ORG repo (identity only, no rewrite)
git config user.email
# → <FOO_ORG email address>
Why Not Shell Functions¶
A shell function switching approach (e.g. github_foo_org() / github_private()) would:
- require remembering to invoke the function before committing
- affect the global config (wrong identity in other terminals)
- not work with Git GUIs, IDEs or background tooling
Conditional includes are automatic, per-repository and tooling-independent — matching the same design principles as the SSH layer.
Prerequisites¶
- Git ≥ 2.36 (for
hasconfig:remote.*.urlsupport) - SSH multi-account setup already routing URLs through host aliases
See Also¶
- SSH-Based Multi-Account GitHub Authentication — prerequisite setup this builds upon
Backlinks¶
No other pages link to this page.