Leveraging advanced gitconfig customization options

The .gitconfig was a configuration file I never gave much attention. When I migrated away from GitHub to self-hosting on Forgejo (see Moving away from GitHub) the need arose to better organize the configurations deployed across my various machines. Reading through the documentation I found one option in particular I was not aware of: conditional includes.

The problem

I use multiple git forges. On my personal machine I push to both GitHub and my self-hosted Forgejo instance. On my work machine I additionally push to a corporate GitLab. Each forge has its own email address, signing key, and commit settings. I wanted all of this handled automatically without having to set it per repository.

includeIf to the rescue

Git's includeIf directive lets you pull in a separate config file only when a condition is met. The condition I use is hasconfig:remote.*.url, which matches against any remote URL in the current repository:

[include]
    path = ~/.gitconfig-base
[includeIf "hasconfig:remote.*.url:git@github.com*/**"]
    path = ~/.gitconfig-github
[includeIf "hasconfig:remote.*.url:git@mydomain.tld*/**"]
    path = ~/.gitconfig-forgejo
[includeIf "hasconfig:remote.*.url:ssh://git@corporate.tld/**"]
    path = ~/.gitconfig-work

The base config is always included first and sets the defaults: my default name, email, delta pager settings, rebase options, push behavior, and so on. The conditional includes then override only what needs to differ per forge, mainly the email and SSH signing key:

# .gitconfig-forgejo
[user]
    name = ...
    email = ...
    signingkey = ssh-ed25519 AAAAC3...
[commit]
    verbose = true
    gpgsign = true

The ordering matters

The base config deliberately turns off commit signing (gpgsign = false). The conditional includes then turn it back on only for the forges where I have signing keys set up. Because git applies includes in order and later values override earlier ones, placing the conditional includes after the base include ensures the per-forge settings win.

Conclusion

This setup means I never touch per-repository git config for identity. Cloning a repo from GitHub automatically uses the GitHub email and signing key. Cloning from Forgejo picks up the Forgejo settings. Everything is driven by the remote URL.

Posted in automation