Computer stuff

Managing git config by folder with includeIf

I have accounts to different Git forges: GitHub, GitLab, where I have a personal and professional accounts, as well as Codeberg, and hopefully one day, my self-hosted Forgejo. I keep all of my local repositories neatly organized in subfolders like this:

.
├── dev
│   ├── gitlab
│   │   ├── Richard-Degenne
│   │   │   └── repo-1
│   │   └── Perfect-Memory
│   │       └── repo-2
│   └── github
│       └── repo-3
│   └── github
│       └── repo-3

This is pretty neat, but it poses one very specific challenge. My accounts do not use the same e-mail addresses. For example, my professional GitLab account uses my work e-mail address. And even for my personal accounts, I use either sub-addressing or my own e-mail server.

Because of this, configuring the e-mail address I use for commits becomes a bit of a hassle. I can't use git config --global user.email because that would mean that all repositories would use the same e-mail address, which is not what I need.

The hard way would be to not have a global e-mail address, and use git config --local user.email in each of my repositories, but that would be ungodlily (yep, that's a word!) tedious.

Surely there's an elegant way to go about it? So I went digging in the documentation for git config...

A hidden gem?

Introducing... Conditional includes. In its infinite wisdom, Git has a way to include a separate .gitconfig file if and only if certain conditions are met. Among the available operators are gitdir, which checks whether the current repository's .git path matches a certain pattern. Isn't that fabulous?

So here's the plan: create multiple .gitconfig files that describe my various identities, and, in the global ~/.gitconfig, use includeIf directives to include them based on the path of the repository. Sounds simple enough? Here we go.

Let's start by creating these unitary .gitconfig files:

; dev/gitlab/Richard-Degenne/.gitconfig
[user]
  email = <my personal GitLab e-mail address>

; dev/gitlab/Perfect-Memory/.gitconfig
[user]
  email = <my work e-mail address>

; And so on and so forth for my different identities...

And, in my main ~/.gitconfig file:

[includeIf "gitdir:~/dev/gitlab/Richard-Degenne/"]
	path = ~/dev/gitlab/Richard-Degenne/.gitconfig

[includeIf "gitdir:~/dev/gitlab/Perfect-Memory/"]
	path = ~/dev/gitlab/Perfect-Memory/.gitconfig

; ...

Alternatively, you can also set these sections from the command line:

git config --global includeIf.gitdir:~/dev/gitlab/Richard-Degenne/.path ~/dev/gitlab/Richard-Degenne/.gitconfig

And there we go! You can test your setup by going into a repository and querying git config --local user.email and seeing that it returns the right address. How cool is that!

It's even better with SSH!

Obviously, there are probably a ton of other neat use-cases for this feature.

For example, since I try to have good security hygiene, I use separate SSH keys for my different accounts, and I use the same conditional include feature to customize which key to use on a per-folder basis with the <a href="https://git-scm.com/docs/git-config#Documentation/git-config.txt-coresshCommand">core.sshCommand</a> setting:

; dev/gitlab/Richard-Degenne/.gitconfig
[core]
  sshCommand = ssh -i ~/.ssh/id_personal

; dev/gitlab/Perfect-Memory/.gitconfig
[core]
  sshCommand = ssh -i ~/.ssh/id_professional

Conclusion

Definitely an article on the shorter side of things, but I've been struggling to write often, so I though why not share this little tidbit! Anyway, very neat feature, 10/10 would recommend. Also, take a look at the other available operators. I don't think I have a use for them, but you might!

A question, a feedback? Write a comment!