Git IncludeIf for Multiple Git Identities
When you maintain both work and personal projects, it is easy to use the wrong Git identity: committing to a company project with a personal email, or exposing a work email in an open-source project. Manually switching Git config is tedious and error-prone.
Git includeIf can automatically load different config files based on conditions, which makes it a good fit for managing multiple identities.
Why Do We Need includeIf?
In daily development, we often need to switch between different identities:
- Work projects: Using a company email (
[email protected]), company GPG signing key, company SSH key - Personal projects: Using a private email (
[email protected]), personal GPG key, personal SSH key - Open-source contributions: Possibly another set of configurations
Without includeIf, you would need to:
- Remember to run
git config user.email [email protected]every time you switch projects. - Or manually set local configurations in each repository.
- Repeatedly check if the correct identity is being used before committing.
This manual approach is tedious and error-prone. Once you commit with the wrong identity and push to the remote repository, it can be difficult to fix.
What is includeIf?
includeIf is a conditional configuration inclusion feature introduced in Git 2.13 (May 2017). It allows you to automatically load different configuration files based on specific conditions (such as repository path, remote URL, current branch, etc.).
The basic syntax is as follows:
[includeIf "condition"]
path = path/to/config/file/to/includeWhen Git reads the configuration, it evaluates the condition. If the condition is met, the content of the specified configuration file will be included, and its configurations will override previous settings.
Common includeIf Conditions
I. Based on Directory Path (gitdir)
This is the most commonly used method, determining which configuration to use based on the repository’s directory:
[includeIf "gitdir:~/work/"]
path = ~/.gitconfig-work
[includeIf "gitdir:~/personal/"]
path = ~/.gitconfig-personalNotes:
- The trailing
/in the path is important!~/work/will match all subdirectories within that directory. - If written as
~/work(without the slash), it will only precisely match this path. - The tilde
~will automatically expand to the user’s home directory.
II. Case-Insensitive Path Matching (gitdir/i)
Especially useful on Windows systems:
[includeIf "gitdir/i:C:/Work/"]
path = C:/Users/username/.gitconfig-workIII. Based on Branch Name (onbranch)
Loads configuration based on the current branch:
[includeIf "onbranch:main"]
path = ~/.gitconfig-mainIV. Based on Remote URL (hasconfig:remote.*.url) ⭐
This is a powerful feature introduced in Git 2.36 (April 2022) that allows configuration to be determined based on the repository’s remote URL. This is also the focus of this article.
[includeIf "hasconfig:remote.*.url:https://github.com/**"]
path = ~/.gitconfig-github
[includeIf "hasconfig:remote.*.url:https://gitlab.company.com/**"]
path = ~/.gitconfig-workPractical Example: Using hasconfig:remote.*.url to Distinguish Identities
Now let’s look at a complete configuration example demonstrating how to elegantly manage both work and personal identities.
Main Configuration File ~/.gitconfig
[core]
autocrlf = input
[commit]
gpgsign = true
[gpg]
format = ssh
[includeIf "hasconfig:remote.*.url:work:<name>/**"]
path = /home/nite/.ssh/work.gitconfig
[includeIf "hasconfig:remote.*.url:personal:<name>/**"]
path = /home/nite/.ssh/personal.gitconfigHere, work:<name> and personal:<name> use Git’s URL alias feature.
Work Configuration ~/.gitconfig-work
[user]
name = "Your Work Name"
email = "[email protected]"
signingKey = "~/.ssh/id_work.pub"
[commit]
gpgsign = true
[core]
sshCommand = "ssh -i ~/.ssh/id_work -o IdentitiesOnly=yes"This configuration file will automatically take effect when you operate company GitLab repositories, including:
- Work email
- Work SSH signing key
- Forced GPG signing
- Specifies the use of a dedicated work SSH key for authentication
Personal Configuration ~/.gitconfig-personal
[user]
name = "Your Personal Name"
email = "[email protected]"
signingKey = "~/.ssh/id_personal.pub"
[commit]
gpgsign = false
[core]
sshCommand = "ssh -i ~/.ssh/id_personal -o IdentitiesOnly=yes"Personal project configuration is similar but uses:
- Personal email
- Personal SSH signing key
- Option not to force signing
- Uses a personal SSH key for authentication
hasconfig vs gitdir: Which to Use?
Both methods have their pros and cons:
| Feature | gitdir | hasconfig:remote.*.url |
|---|---|---|
| Decision Basis | File system path | Remote repository URL |
| Min Git Version | 2.13+ (2017) | 2.36+ (2022) |
| Evaluation Speed | Very fast | Slightly slower (requires scanning) |
| Flexibility | Requires organized directory structure | Location independent |
| Use Case | Projects with fixed directories | Projects scattered everywhere |
Recommended Strategy:
If you are accustomed to placing work and personal projects in different directories, using gitdir is the simplest:
[includeIf "gitdir:~/work/"]
path = ~/.gitconfig-work
[includeIf "gitdir:~/personal/"]
path = ~/.gitconfig-personalIf your projects are scattered everywhere, or you need to differentiate identities based on different Git hosting platforms, using hasconfig:remote.*.url is more flexible:
[includeIf "hasconfig:remote.*.url:https://gitlab.company.com/*/**"]
path = ~/.gitconfig-work
[includeIf "hasconfig:remote.*.url:https://github.com/personal/**"]
path = ~/.gitconfig-personalYou can also combine both for simplicity and flexibility.
Frequently Asked Questions
Question 1: Configuration not taking effect
Check the following:
- Is there a trailing slash in the path (
~/work/instead of~/work)? - Is the configuration file path correct (using absolute paths is safer)?
- Is your Git version new enough (
git --version)? - Is includeIf placed at the end of the configuration file?
Question 2: hasconfig pattern mismatch
# Check remote URL
git remote -v
# Check URL format
git config --get remote.origin.urlEnsure your pattern correctly matches the remote URL format.
Question 3: Multiple configuration conflicts
Git configuration priority from high to low:
- Command-line arguments (
git -c [email protected]) - Local repository configuration (
.git/config) - includeIf included configuration
- Global configuration (
~/.gitconfig) - System configuration (
/etc/gitconfig)
Later-read configurations will override earlier-read ones.