Git includeIf Tutorial: Switch Identity by Folder

includeIf is a Git config feature that loads another config file only when the repository lives under a certain folder — the cleanest terminal-native way to have two identities on one machine. Organize repositories under folder trees (e.g. ~/code/work/ and ~/code/personal/, or Windows C:/Users/YOU/code/work/), write one small file per identity, and Git automatically applies the right user.name/user.email the moment you cd into a repository. No scripts, no per-repo git config — folder location decides identity, forever.

Answer: In ~/.gitconfig, add [includeIf "gitdir/i:C:/Users/YOU/code/work/"] → path = C:/Users/YOU/.gitconfig-work (repeat for personal). The trailing slash and the i (case-insensitive) matter on Windows. Each included file holds that identity's user.* block.

What includeIf is (in one paragraph)

Git reads your global config (~/.gitconfig) for every command. An includeIf section says: also load this other file — but only if the current repository's directory matches this pattern. Because the match is on the repository's path, repositories under different trees silently inherit different settings. It's a conditional #include at the config level.

Step 1 — sort your repositories into folders

C:/Users/YOU/code/work/        ← all work repositories
C:/Users/YOU/code/personal/    ← all personal repositories

Move existing repositories into these trees (Git doesn't care — history and remotes travel with the folder). Everything you clone from now on goes into the right tree by habit.

Step 2 — create the identity files

# C:/Users/YOU/.gitconfig-work
[user]
    name = Work Name
    email = me@company.com

# C:/Users/YOU/.gitconfig-personal
[user]
    name = Personal Name
    email = me@personal.com

Nothing else in these files — keep them single-purpose. Add pull.rebase true or similar only if you want it per tree.

Step 3 — wire the conditions into ~/.gitconfig

# C:/Users/YOU/.gitconfig
[includeIf "gitdir/i:C:/Users/YOU/code/work/"]
    path = C:/Users/YOU/.gitconfig-work

[includeIf "gitdir/i:C:/Users/YOU/code/personal/"]
    path = C:/Users/YOU/.gitconfig-personal

[user]
    name = Fallback Name
    email = fallback@example.com

Notes that break half of all first attempts:

  • Trailing slash is required — gitdir/ matches directories under the path; without / at the end you'll match nothing.
  • gitdir/i: vs gitdir: — the i makes the match case-insensitive; on Windows drive letters and user paths often differ in case, so keep the i.
  • Use forward slashes in the pattern even on Windows, or escape backslashes carefully.
  • Fallback block last — the global [user] applies wherever no include matched; set it to something harmless or keep your primary identity there.

Step 4 — verify

cd C:/Users/YOU/code/work/some-repo
git var GIT_AUTHOR_IDENT
# → Work Name <me@company.com> ...

cd C:/Users/YOU/code/personal/other-repo
git var GIT_AUTHOR_IDENT
# → Personal Name <me@personal.com> ...

# confirm which includes fired
git config --show-origin --get-regexp "^user\."

New commits in each tree now carry the right author automatically — GitHub attributes them to the matching account.

What includeIf does NOT fix

LayerHandled?Still needs
Commit author (identity)Yes — that's the point—
Push authentication (HTTPS)NoPer-repo credentials: useHttpPath + one sign-in per repository (see Git Credentials Explained)
Push authentication (SSH)No — but pairs wellOne key per account + host aliases; identity applies regardless of which key pushes
gh CLI active accountNogh auth switch --user ...

includeIf owns the author; the credential layer still needs its own per-repository logic — or a client that binds both.

Troubleshooting

  • Nothing changes after edits — re-run from the repository folder; config is read per command, but a wrong pattern silently matches nothing. Test the pattern with git config --show-origin --get user.email.
  • Works for one tree, not the other — almost always the trailing slash or drive-letter case; keep gitdir/i: + full path + /.
  • Repos live outside both trees — they get the fallback [user]; either widen the patterns or accept the default.
  • Submodules — submodule paths are matched too; keep them inside the same tree as their parent.

The zero-config version

includeIf is the right tool if you want terminal-native, transparent, versionable config. If you'd rather not think about folders, identity files, and credential entries at all: GITmaxed gives you the same outcome without any of it — every account stays signed in, each repository has an explicit account binding, and commits are authored as that account. Folder trees taught you the model; a multi-account client just enforces it.

Related questions answered (the same queries, one by one)

How do I use different git user.name and user.email per project?

Either set them per repository (git config user.name without --global) or, at scale, use includeIf folder rules so identity follows the repository's location automatically.

What does gitdir/i mean in git config?

gitdir/ matches repositories under a directory (trailing slash required); /i makes the comparison case-insensitive — important on Windows.

Why is my includeIf not matching anything on Windows?

Usually a missing trailing slash, backslash-vs-forward-slash mismatch, or drive-letter case difference. Use gitdir/i: with forward slashes and a trailing /.

Does includeIf change which account pushes?

No — it only changes config (identity). Pushes still use whatever credential (HTTPS) or SSH key the repository's URL points at; combine with per-repo credentials or per-account keys.

Is includeIf better than editing user.email per repository?

For many repositories organized by account, yes — one-time setup, automatic forever, and new clones inherit it from their folder. For two repos, per-repo config is fine.

Can includeIf load different SSH keys per folder?

Yes — via core.sshCommand in each included file (e.g. ssh -i ~/.ssh/id_ed25519_work -o IdentitiesOnly=yes), though host aliases in ~/.ssh/config are usually cleaner.

Is there a GUI alternative to setting up includeIf?

Yes — GITmaxed binds accounts to repositories directly in the app, producing the same per-repository identity without folder-based config files.

Post a Comment