DEV Community

Cover image for Modularizing your git config with conditional includes
Thomas Hartmann
Thomas Hartmann

Posted on • Originally published at thomashartmann.dev on

Modularizing your git config with conditional includes

Do you track your git config across machines or keep it in sync with your dotfiles? Is it full of settings that you want to share between all your different contexts? Are there certain things that you want to change depending on what the context is? Well, I’ve got news for you!

tl;dr:

If you want to use an additional config file for all subdirectories below a certain path, use the includeIf functionality that was introduced in git 2.13.0.

[includeIf "gitdir:/"]
  path = path/to/your/.config

That’s all you need to get going, but if you want to know more about how this works and some caveats you might to be aware of, keep reading.

include and includeIf

First off, I’d be remiss not to direct you to the official documentation for this feature, which can be found here. However, there’s loads more info there than you might need (and want), so let’s extract the important bits.

The include and includeIf sections work the same, except the includeIf has a condition that must be satisfied. They let you insert configuration from another file into your main one.

In my case, this meant that I could automatically change my email whenever the git directory was a subdirectory of ~/projects/work, allowing me a simple and efficient way to always use my work email for work, without changing my global git config or branching off from my main dotfiles repo.

Here’s the relevant extract from my config:

[includeIf "gitdir:~/projects/work/"]
  path = ~/projects/work/.gitconfig

I keep a separate config file in the ~/projects/work directory that overrides my email.

This would also be useful if your team has specific rules about whitespace, merge strategies, comment characters, etc. that you want to enforce.

Things that might trip you up

Syntax

Note the trailing slash after the directory path in the includeIf line. This makes it so that it will match all subdirectories of the specified directory. As explained by the docs:

If the pattern ends with /, ** will be automatically added. For example, the pattern foo/ becomes foo/** . In other words, it matches “foo” and everything inside, recursively.

This also means that if there is no trailing slash, it’ll match only that specific directory.

File insertion

Here’s another quote from the documentation:

The contents of the included file are inserted immediately, as if they had been found at the location of the include directive. If the value of the variable is a relative path, the path is considered to be relative to the configuration file in which the include directive was found.

So you’ll probably want to put the includes at the bottom of your files to make sure the included config isn’t overridden later on in the source file.


I hope that cleared some things up for you and that you found it useful; I know I did. If you want more in-depth information, see the documentation.

Top comments (0)