obsidian/wiki/concepts/git-includeif-per-remote.md
2026-04-24 11:19:08 +01:00

111 lines
4.4 KiB
Markdown

---
title: "Git — Per-Remote Identity with includeIf"
aliases: [git-includeif, git-multiple-identities, git-work-personal-email, git-conditional-config]
tags: [git, dotfiles, identity, ssh, bitbucket, github]
sources:
- "daily/2026-04-23.md"
created: 2026-04-23
updated: 2026-04-23
---
# Git — Per-Remote Identity with includeIf
Git's `includeIf` directive in `.gitconfig` applies a supplemental config file only when a condition matches. The `hasconfig:remote.*.url` variant matches on the remote URL of the current repository, making it possible to automatically switch git identities (email, signing key, etc.) based on whether a repo is hosted on GitHub vs Bitbucket or any other remote — without any per-repo manual config.
## Key Points
- **`includeIf "hasconfig:remote.*.url:*github.com*"`** matches any repo with a GitHub remote — applies a separate `.gitconfig-github` file automatically
- Eliminates the need to run `git config user.email` in every new personal repo — the correct identity is applied by remote URL
- The condition uses glob-style wildcards: `*github.com*` matches both `https://github.com/...` and `git@github.com:...`
- More robust than `includeIf "gitdir:~/projects/personal/"` (directory-based) — works regardless of where the repo is cloned
- Order matters: the included file is applied after the main config, so it overrides values in `.gitconfig`
## Details
### The Problem This Solves
Working with multiple git identities (work email for Bitbucket/Oliver repos, personal email for GitHub) previously required remembering to run `git config user.email` in each new personal repo. Forgetting resulted in commits to GitHub attributed to the work email. Remote-based `includeIf` makes this automatic and invisible.
### `.gitconfig` Setup
```ini
# ~/.gitconfig — main config (default = work identity)
[user]
name = Vadym Samoilenko
email = vadymsamoilenko@oliver.agency
# Override with personal identity for GitHub repos
[includeIf "hasconfig:remote.*.url:*github.com*"]
path = ~/.gitconfig-github
```
```ini
# ~/.gitconfig-github — personal identity
[user]
email = samoylenko.vadym@gmail.com
```
After this setup, any repo with a `github.com` remote automatically uses the personal email. Bitbucket, internal GitLab, and other remotes use the default work email.
### Verifying the Correct Identity
```bash
# In a GitHub repo
git config user.email
# → samoylenko.vadym@gmail.com
# In a Bitbucket/work repo
git config user.email
# → vadymsamoilenko@oliver.agency
```
### SSH Key Separation (Complementary)
`includeIf` handles commit identity (who authored the commit). SSH key selection (which credential is used to authenticate the push) is handled separately in `~/.ssh/config`:
```ssh
# ~/.ssh/config
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_github
Host bitbucket.org
HostName bitbucket.org
User git
IdentityFile ~/.ssh/id_ed25519_bitbucket
```
Both pieces are needed: `includeIf` for commit metadata, `~/.ssh/config` for authentication.
### Alternative: Directory-Based includeIf
If the remote URL approach is too broad, a directory-based condition is more explicit:
```ini
[includeIf "gitdir:~/personal/"]
path = ~/.gitconfig-github
```
This applies the override only to repos inside `~/personal/`. The downside: repos cloned anywhere else won't get the override automatically.
### Migration: Adding includeIf to an Existing Config
When migrating from a single identity to multiple identities:
1. Set the work email as the default in `~/.gitconfig`
2. Create `~/.gitconfig-github` with the personal email
3. Add the `includeIf` block to `~/.gitconfig`
4. Verify in an existing GitHub repo: `git config user.email`
Past commits already made with the wrong email are not affected — `includeIf` only applies to future commits.
## Related Concepts
- [[wiki/concepts/fish-shell-path-config]] — SSH aliases as Fish functions complement this SSH config approach
- [[wiki/concepts/remote-server-dotfiles-bootstrap]] — dotfiles migration context where this pattern was configured
- [[wiki/concepts/bitbucket-mcp-atlassian]] — Bitbucket identity context (one of the two remotes managed by this config)
## Sources
- [[daily/2026-04-23.md]] — New workstation SSH/git migration session: git identity split required between `vadymsamoilenko@oliver.agency` (Bitbucket/work) and `samoylenko.vadym@gmail.com` (GitHub); `includeIf "hasconfig:remote.*.url:*github.com*"` selected as the mechanism