Using Unique SSH Keys for Multiple GitHub Accounts

Amanda Reilly
3 min readNov 28, 2020

As a software engineer and all-around nerd, I’m pretty picky about computers. The Mac Mini provided by my company is fine, but, let’s face it, my custom-built desktop gaming rig and my Dell XPS 15 laptop (MacBook power at half the price — seriously, you should check it out!) both blow it out of the water in terms of performance.

Windows Subsystem for Linux (WSL) and the VS Code ecosystem have both matured to the point where I can use Windows for development (without dual-booting Linux!). Since the pandemic started, I‘ve been using my personal equipment for work, and it’s been fabulous. So I was excited to start working on some new side projects this week during my vacation.

People, IT SUCKS. Seriously. It’s painful. I have separate GitHub accounts for work and personal projects, each of which requires a unique SSH key. Since I already had my work SSH key set up on my machine, I couldn’t actually work with any of my personal repos.

A screenshot from a computer terminal window showing git access denied error with a “denied” stamp graphic overlaid on top.
GitHub doesn’t like multiple accounts. :(

Googling “how to use different ssh keys for different GitHub accounts” led to a lot of instructions for messing with my SSH config that didn’t even work, and actually broke the GitHub SSH connection on my work account.

Luckily, a random sighting in the comments of an SO thread, plus a deep dive into the git config documentation led to an epiphany: includeIf. This innocuous-looking command was the key to my GitHub conundrum.

With a single GitHub account, you have a single .gitconfig file. This is usually located in your home directory. It defines things like your name, email address, and other random git settings. However, if you’re like me and need to juggle multiple GitHub accounts, it’s not quite enough. This is where includeIf comes in. By adding it to my main .gitconfig, I was able to conditionally include other config files based on the current directory. Combined with the core.sshCommand option, this was the perfect fix for my GitHub woes. Here’s how I did it:

(Note: the commands below worked on my WSL setup powered by Ubuntu 20.04. If you’re using macOS or a different Linux distro, you might need to tweak them a bit. And if you’re using plain ol’ Windows, I’m sorry.)

Start by copying your current .gitconfig file, once for each profile you need to create. Since I have work and personal profiles, I made two.

cp ~/.gitconfig ~/.gitconfig-work
cp ~/.gitconfig ~/.gitconfig-personal

You should now have three separate files. Open them all in your editor of choice. If you’re using VS Code (and you’ve added it to your path), you can open them all in one shot like this:

code ~/.gitconfig ~/.gitconfig-work ~/.gitconfig-personal

In your main .gitconfig file, remove any account-specific settings. I left anything that would be the same across both accounts, like my pull.rebase setting. At the top of your cleaned-up file, add the following block once for each profile. Make sure to edit your paths and file names as necessary:

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

In your .gitconfig-work and .gitconfig-personal files, remove any shared configuration, and edit the user name and email. Add the following snippet to each, making sure to change the key names accordingly.

[core]
sshCommand = ssh -i ~/.ssh/id_rsa -F /dev/null

My final files look like this:

A screenshot of the author’s final .gitconfig file.
A screenshot of the author’s .gitconfig-work file.
My .gitconfig-work file

Now, close your terminal, open a new one, and test it out! You should be able to push and pull all your repos, as long as they are below the directory that matches your includeIf statement for the account that has access to them.

Doesn’t it feel good to solve a problem?

Have you solved any interesting problems recently? I’d love to hear about them!

--

--

Amanda Reilly

Software engineer. Great British Baking Show enthusiast. Obsessed with Beat Saber. Powered by insatiable curiosity and too much Diet Coke.