How to override and share git configuration options between multiple directories
Published: 2021-02-28 14:12:03

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](https://git-scm.com/docs/git-config#_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:

```ini
[includeIf "gitdir:~/myworkprojects/"]
    path = ~/myworkprojects/.gitconfig
```

2. Edit `~/myworkprojects/.gitconfig` and add all the work-specific configurations I want. For example:

```ini
[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 give 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"]` 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:

```ini
[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:

```ini
[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.