Organizing multiple Git identities

https://garrit.xyz/posts/2023-10-13-organizing-multiple-git-identities

Here's a quick tip on how to manage multiple Git identities (e.g. personal, work, client1, client2).

I organize my Git repos in three levels. My personal projects live in a ~/sources directory. All my work projects live in ~/work. This is the first level.

Level 2 is the client, e.g. ~/work/client1. Naturally, level 3 is the project repository: ~/work/client1/foo-api.

This is how my work directory is organized:

/Users/garrit/work
├── client1
│   ├── foo-api
│   ├── foo-ios
│   └── foo-android
└── client2
    ├── bar-ios
    └── bar-middleware

Now, say that client2 demands that we commit with a different identity than our default work email. Besides that, you probably also have a personal email address for your own projects. How do you manage that?

.gitconfig includes

The global configuration file for Git is ~/.gitconfig. If you've ever set a parameter like git config user.name "Foo Bar": this is where it ended up.

One awesome feature of the .gitconfig file is that you can conditionally include other config files, and this is what does the trick. Here's my ~/.gitconfig file:

[user]
    name = Garrit Franke
    email = garrit@slashdev.space

[includeIf "gitdir:~/work/"]
    path = ~/.gitconfig-work

[includeIf "gitdir:~/work/client2/"]
    path = ~/.gitconfig-client2

[includeIf "gitdir:~/sources/"]
    path = ~/.gitconfig-personal

# ...

By default, my name and email are always set to my personal identity. I also store some other global settings here, but those are not relevant for this post. If the repository is located inside the ~/work directory, a file named ~/.gitconfig-work is included. This is just another gitconfig file. This is what that looks like in my case:

[user]
    name = Garrit Franke
    signingkey = 12345678
    email = garrit@work.de

[commit]
    gpgsign = true

I hope you'll see where this is going. For every identity, you keep a separate gitconfig file and include it in the main ~/.gitconfig. Crucially, this requires you to organize your repositories grouped by client.

This trick has simplified my project onboarding quite a bit. No more "You forgot to update your Email Address" requests from clients!


You can also filter based on the remote URL!

; include only if a remote with the given URL exists (note
; that such a URL may be provided later in a file or in a
; file read after this file is read, as seen in this example)
[includeIf "hasconfig:remote.*.url:https://example.com/\*"]
    path = foo.inc
[remote "origin"]
    url = https://example.com/git*