Modularizing your git config with conditional includes
Tags: git, gitgud
Published: 2019-08-19 06:31:22

---
title: Modularizing your git config with conditional includes
published: true
tags: git, git gud
canonical_url: https://thomashartmann.dev/blog/modularizing-your-git-config-with-conditional-includes
cover_image: https://thomashartmann.dev/images/modularizing-git-config.svg
---
<div><p>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!</p>
<h2 id="tldr">tl;dr:</h2>
<p>If you want to use an additional config file for all subdirectories below a certain path, use the <code>includeIf</code> functionality that was introduced in git 2.13.0.</p>

```conf
[includeIf "gitdir:<path to top directory to use the config in>/"]
  path = path/to/your/.config
```

<p>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.</p>
<h2 id="include-and-includeif">
<code>include</code> and <code>includeIf</code>
</h2>
<p>First off, I’d be remiss not to direct you to the official documentation for this feature, which can be found <a href="https://git-scm.com/docs/git-config#_conditional_includes">here</a>. However, there’s loads more info there than you might need (and want), so let’s extract the important bits.</p>
<p>The <code>include</code> and <code>includeIf</code> sections work the same, except the <code>includeIf</code> has a condition that must be satisfied. They let you <strong>insert configuration from another file</strong> into your main one.</p>
<p>In my case, this meant that I could automatically change my email whenever the git directory was a subdirectory of <code>~/projects/work</code>, 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.</p>
<p>Here’s the relevant extract from my config:</p>
```conf
[includeIf "gitdir:~/projects/work/"]
  path = ~/projects/work/.gitconfig
```

<p>I keep a separate config file in the <code>~/projects/work</code> directory that overrides my email.</p>
<p>This would also be useful if your team has specific rules about whitespace, merge strategies, comment characters, etc. that you want to enforce.</p>
<h2 id="things-that-might-trip-you-up">Things that might trip you up</h2>
<dl>
<dt>Syntax</dt>
<dd>
<p>Note the trailing slash after the directory path in the <code>includeIf</code> line. This makes it so that it will match all subdirectories of the specified directory. As explained by the docs:</p>
<blockquote>
<p>If the pattern ends with <code>/</code>, <code> **</code> will be automatically added. For example, the pattern <code>foo/</code> becomes <code>foo/** </code>. In other words, it matches “foo” and everything inside, recursively.</p>
</blockquote>
<p>This also means that <strong>if there is no trailing slash, it’ll match only that specific directory</strong>.</p>
</dd>
<dt>File insertion</dt>
<dd>
<p>Here’s another quote from the documentation:</p>
<blockquote>
<p>The contents of the included file are <strong>inserted immediately, as if they had been found at the location of the include directive</strong>. 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.</p>
</blockquote>
<p>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.</p>
</dd>
</dl>
<hr>
<p>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 <a href="https://git-scm.com/docs/git-config#_conditional_includes">the documentation</a>.</p></div>