Skip to content

Instantly share code, notes, and snippets.

@sudoforge
Last active July 13, 2024 04:20
Show Gist options
  • Save sudoforge/e793283851ee04fcaae0fc9d3dfdcca9 to your computer and use it in GitHub Desktop.
Save sudoforge/e793283851ee04fcaae0fc9d3dfdcca9 to your computer and use it in GitHub Desktop.
Managing multiple Git identities

Managing multiple Git identities

This gist exists to display how I manage my Git configuration for different identities (e.g. personal and work identities) using the default configuration chain in Git.

My global git configuration is stored in my dotiles repository, which is public, but includes no work-related git configuration. Instead, that lives in and is managed by other files on my system, which are not synced to that public dotfiles repository. With just a few small configuration changes, you can learn how to do this too.

First, organize your repositories

This process relies on the includeIf conditional include statement within Git's configuration file, and a little on-disk organization is necessary in order to avoid introducing a heavy maintenance burden (e.g. needing to add new configuration for each repo you clone).

There's just one rule:

  • Per identity, have a common parent folder in which you clone all of the relevant repositories

As an example, I have a folder called code in my user's home directory (~). Within this folder lives every repository I have or will ever clone, namespaced by the repository URI. For example, a repository located at github.com/foo/bar is cloned to ~/code/github.com/foo/bar.

When cloning a new repo, you can do this in one shot (git will create folders that don't exist):

git clone [email protected]:foo/bar.git ~/code/github.com/foo/bar

Note

You can follow this same pattern of organizing your repositories, if you wish, or come up with your own system that aggregates all identity-related repositories into a parent folder unique to them. It could be as simple as ~/code/work and ~/code/personal!

Including a "local" file

The first part of this process is to include a local configuration file at the bottom of my global git configuration file. This file doesn't need to exist! If it doesn't exist, Git will quietly ignore it (you won't get errors while running git commands).

Place this at the very bottom of your git configuration:

[include]
	path = ~/.config/git/config.local

Tip

You can name this file whatever you want -- just be sure to provide the right filename.

You can skip this step if you do not plan on sharing your global configuration file.

This step provides a layer of abstraction between your includeIf statements and your global Git configuration file. I find this useful if you plan to share it, as it hides your on-disk file layout, and the different identities you manage. It also allows for per-machine customization, if you plan to re-use your global configuration file on more than one machine (e.g. your personal and work machines, or several personal machines).

Creating the local configuration file

It's pretty simple: all it does is set up conditional include statements based on the path. Because we're organizing all of our work-related repositories into a single folder, this becomes pretty easy!

As an example, let's create a conditional statement for our "work" repositories.

[includeIf "gitdir:~/code/work/"]
	path = ~/.config/git/config.work

The includeIf statement here is stating that if we're in a git repository (either at the root or in a subdirectory) within the ~/code/work folder, then a ~/.config/git/config.work configuration file should be included.

Note

This file is created on each unique machine I use (I only have one laptop) and is backed up outside of my dotfiles repo.

Creating configuration for the identity

Next, we need to create that ~/.config/git/config.work configuration file. Because this adds to your global configuration, you can set overrides here (for example, for user.email, user.signingkey), or add entirely new configuration properties (like aliases).

I'll leave the specific implementation up to you, but here's a quick example of what yours might look like:

[user]
	name       = John Doe
	email      = [email protected]
	signingkey = ABCMYWORKSIGNINGKEY

Note

This will override any user.name, user.email, and user.signingkey properties set earlier in your default global configuration file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment