How to override and share git configuration options between multiple directories

Sometimes I have a set of projects for which I want to override a few git configuration options. For example, I have a directory with all the git repositories for my work projects. For those work repositories, I want to use my company’s email address and GPG signing key instead of my personal ones.

The obvious way to do it is to set the relevant git configuration options in each of the directories but if there are many projects, it becomes a tedious process. And if I ever want to change something, I’ll have to do it all over again.

Luckily, there’s a better way: Git Conditional Includes!

This allows us to add configuration files conditionally, depending on the folder in use. In other words, we can tell git to use different configuration options depending on the repository path.

For example, let’s say I keep all my work projects under ~/myworkprojects. All I need to do is:

  1. Edit my global git configuration in ~/.gitconfig and add:
[includeIf "gitdir:~/myworkprojects/"]
    path = ~/myworkprojects/.gitconfig
  1. Edit ~/myworkprojects/.gitconfig and add all the work-specific configurations I want. For example:
[user]
    email = myemail@mycompany.com
    signingkey = ABC123DEF456...

And that’s it!

Now all the repositories inside ~/myworkprojects will use my work email and signing key, while anything outside that folder will retain the default configuration. And if we have other folders with multiple repositories for which we want to override configuration options, we can add more includeIf settings in ~/.gitconfig.

We can even define paths that match any directory that ends with our given pattern. An example from the docs:

[…] the pattern foo/bar becomes **/foo/bar and would match /any/path/to/foo/bar.

On the other hand, if we don’t add a trailing slash to the gitdir keyword, it will not match sub-folders recursively. For example: [includeIf "gitdir:/foo/bar/"] would match /foo/bar/baz and /foo/bar/boo but [includeIf "gitdir:/foo/bar"] (no trailing slash) would only match /foo/bar and nothing else inside it.

One other detail to keep in mind is: includeIf includes the file we specify as if we copied and pasted its contents. This means it should be set after the option(s) we want to override in ~/.gitconfig. Otherwise, they will be overridden again.

For example, if our .gitconfig looks like this:

[includeIf "gitdir:~/myworkprojects/"]
    path = ~/myworkprojects/.gitconfig
...
[user]
    email = myemail@mycompany.com
    signingkey = ABC123DEF456...

The [user] options in ~/myworkprojects/.gitconfig will not take effect because they would be overridden later in ~/.gitconfig.

On the other hand, if we do this:

[user]
    email = myemail@mycompany.com
    signingkey = ABC123DEF456...
...
[includeIf "gitdir:~/myworkprojects/"]
    path = ~/myworkprojects/.gitconfig

We will be doing the exact opposite: we first specify the [user] options and then we override them with the values from the included file.

Since the goal is to override the options set in the global config, I just pop the includeIf at the end of ~/.gitconfig to make sure nothing else will get in the way.