Lead a code double life

anonymous guy in front of a laptop

“I want to contribute code to this project, but I want to keep those contributions separate from my IRL identity. But git is big and complicated, and if something is misconfigured the risk is huge (I'll mix up my identities!), and now I don't really feel like thinking about it anymore... those contributions weren't that important anyways...”

Does this sound like you? It sure did sound like myself a few years back! nowadays I can at least say I've arrived close enough to git zen and git mindfulness that I no longer let the fear of “messing up my git/ssh configuration” get in the way of contributing!

My ideal solution would to be able to quickly clone any repository as any identity on any machine, have minimal manual intervention in the process, and when doing a git commit not have to worry about leaking any information from the wrong identity. It's a lot of moving parts in a potentially messy setup, and my current setup, while not perfect, at least gives me peace of mind for the most important aspect (in my opinion): not mixing my identities.

All you need to think about is scoped to the following 3 configuration files.

Each one will be discussed in its own section.

$HOME/.gitconfig

This is your main git configuration, the one you manipulate with --global, the one that git uses when it has no specific instructions about what to do with your git commands.

$ git config --global user.name "John Doe"
$ git config --global user.email "johndoe@example.com"

What I do here is actually not set any identity in the global config! I set my values to empty strings (to be overridden at a per repository level). This gives me a fail-safe system, where a failure to specify will result in not associating with any identity.

$ git config --global user.name ""
$ git config --global user.email ""

In fact, it's probably worth taking a look at what's in your .gitconfig right now!

cat ~/.gitconfig

Just scan it with your eyes! it's probably not that long, and if you see anything that's tied to any of your identities... remove it! 😎

.git/config

This is the place we want to be! The closest your git config can get to the code it relates to.

Now I'm a lazy guy, I haven't made a fancy script or anything to set my per repo configuration. Currently I rely solely on my shell's history (ctrl+r) to fetch the relevant command (it's the same as the commands above, just without the --global parameter.) It works great!

But this means that as far as git is concerned, there shouldn't be any way for information to cross the repo boundaries... great!

$HOME/.ssh/config

Code contributions are not only associated with the version control system you happen to use, but also in the channel of communication (and if you want to be really paranoid, this includes the IP of your commit origin as well). I don't usually take my attribution worries it to the network level, but you might, so it's worth mentioning.

SSH can also be a potential can of worms in terms of configuration, but the way I keep things in order here is to generate separate SSH keys for each of my identities, and tell git to associate to a specific SSH key at the time of the initial git clone. This can be done very cleanly through ssh config aliasing.

Let's say I just created an account on github and I call this identity alice, and I'd like to generate a new SSH key to use with this new separate account.

$ ssh-keygen -f ~/.ssh/alice

Then after I upload this to the accounts 'ssh keys' section in the account settings in the github Web UI. I would now create a section in my .ssh/config.

Host alice.github.com
    User git
    HostName github.com
    IdentityFile ~/.ssh/alice

NOTE: The alias can be anything, and though it here might look like a subdomain, it's not. I just like to keep the original domain in the alias for simplicity, and to have a convention that's easy to remember. When I want to SSH into my most frequently used machines, I of course make those super short to support my laziness! ;)

Now when I want to clone a repository, for example mastodon. I change the clone URL (SSH URL in github Web UI) to look like the one matching my alias.

$ git clone git@alice.github.com:mastodon/mastodon.git

Then I do the (unfortunately) extra step of deliberately associating it with other alice handles (email and commit display name).

$ git config user.name "Alice"
$ git config user.email "alice@example.com"

I only have to do this once per identity-resource pair... which so far works out fairly well, and I then synchronize this file between machines I own (using something like rsync). I make sure to generate new ssh keys for each identity on each machine (so I can revoke a single one), and the configuration will still work across all machines as long as I keep the name of the ssh-key file the same! Nice!

That's it! You now have a fairly simple system for managing multiple identities for code development! 🎉


Wacky words by

Tegaki