Managing Multiple Github Accounts On One Machine
For a whole bunch of reasons, it’s possible to end up with multiple Github accounts - it’s a good idea to keep personal and professional Github accounts separate, for example.
That implies there are situations where it’s necessary to work with multiple Github accounts on the same machine - and that can be painful.
I was usually caught out by this when in a hurry to commit a bug fix, and there were times when I ended up tweaking code in the Github UI rather than fight with local configs.
Finally, I've got around to fixing this once and for all. Here is a process which while not making it pain-free, at least makes it possible with as little hassle as possible.
Assumptions
- You’ve already created the Github accounts and the online side of Github is working.
- You’re doing this on a Mac or similarly *nixy flavoured system.
- I'm using the terms "personal" and "work" accounts in this example, but it would work equally well if you've got different Github accounts for different clients or similar.
How it works
The entire process depends on two factors:
- separate SSH keys for each Github identity (this is enforced by Github themselves)
- leveraging git's ability to conditionally-configure settings depending on where the git-managed project is located in the file system.
Sort out your directory structure
You'll need to start by separating your personal and professional code bases into separate directories - this is how I’ve structured mine:
~
└── data/
└── code/
├── personal/
│ ├── project_1/
│ ├── project_2/
│ ├── project_#/
└── work/
├── project_1/
├── project_2/
├── project_#/
Exactly how you set this up is a matter of taste, but it makes the git configuration a lot easier if all directories containing git-managed code sit underneath one main directory, and you separate the projects from each Github account into a separate subdirectory structure.
Any new projects that you create within the personal
or work
directories will automatically pick up the relevant Github credentials once you’ve completed the setup.
Assuming that works for you, this is the process to get things working properly.
Create SSH keys locally
In this step, you’ll create separate SSH keys, one for each Github account.
- In a terminal, switch to the
~/.ssh
directory - Create a new SSH key for each Github account that you want to work with
ssh-keygen -t rsa -C "your-email-address" -f "github-username"
ssh-add --apple-use-keychain <ssh key name>
This step is semi-optional if you've already got SSH keys set up - just create any that are missing.
Add the new SSH keys to Github
You’ll need to do this 5-step process for each Github account in turn:
- While still in the
~/.ssh
directory, copy the public key to the clipboard withpbcopy < ~/.ssh/<keyname>.pub
- Log into Github with the credentials for the relevant account (it's worth double-checking this, because you don't want to get the SSH keys mixed up between accounts.)
- Click on your avatar at top right, select the
Settings
menu option and then theSSH and GPG keys
item - Add a new SSH key by clicking on the
New SSH key
button - Paste in the public key that you copied in step 1, give it a name, and add it.
Repeat this process for the other Github account(s), remembering to login to that account before adding the SSH key.
Update your SSH config
Still in the ~/.ssh
directory, create (or edit the existing) config
file.
Here, you’re going to create an entry for each Github account:
~/.ssh/config
# personal account
Host github.personal
HostName github.com
User git
IdentityFile ~/.ssh/personal
# work account
Host github.work
HostName github.com
User git
IdentityFile ~/.ssh/work
You can call the accounts whatever you like, but make sure that the Host
value in each section is different. The hostname should be github.com
in both sections. You’ll see why this is important in a moment.
Sort out the git configuration
Create local .gitconfig files
You’re going to create THREE .gitconfig
files:
- one “master” config, which applies to all projects
- one “personal” config, which applies only to personal projects
- one “work” config, which applies only to work projects
The master config just tells git where to look for the other configs; while the other configs control which Github identity gets used.
Master config
We’ll start with the master config. In your “root” code directory - that’s ~/data/code
in my structure - create an empty .gitconfig
file:
~
└── data/
└── code/
├── .gitconfig <-- global config file
├── personal/
└── work/
Update the contents:
# ~/data/code/.gitconfig
[includeIf "gitdir/i:~/data/code/personal/"]
path = ~/data/code/personal/.gitconfig.personal
[includeIf "gitdir/i:~/data/code/work/"]
path = ~/data/code/work/.gitconfig.work
This conditionally-loads one of the two config files, depending on which directory the local repo finds itself. This is where the magic happens, basically - it switches the non-SSH values as needed to allow the full push/pull process to work.
You’ll need to adjust the paths after the gitdir/:i
to fit your directory structure.
Local .gitconfigs
Now let’s create the “local” git configs. You need to do this twice, once for each of the Github accounts:
~
└── data/
└── code/
├── .gitconfig <-- global
├── personal/
│ └── .gitconfig.personal <-- personal
└── work/
└── .gitconfig.work <-- work
The contents of both files have the same structure:
[user]
email = <email address associated with the Github account>
name = <your name>
[github]
user = <your github username>
[credential]
username = <your github username>
Insert the appropriate values for email
, user
, and username
for the relevant account.
Using the process
Now that we’ve got this set up, it’s time to use it for real.
The SSH side of the process relies on replacing the github.com
hostname in the repo’s URL with the hostname that you defined in the SSH config:
- for a “personal” repo, you would use
git@github.personal
- for a “work” repo, you would use
git@github.personal
For example, the Github repo URL for this site is
git@github.com:timd/trashpanda.cc.git
When I’m working with the repo locally, however, that gets replaced with
git@github.personal:timd/trashpanda.cc.git
Then in conjunction with the local git configuration in the relevant subdirectory, the correct Github credentials will automatically be applied when pushing and pulling.
Using this process when cloning a repo for the first time
To do this when cloning an existing repo, copy the repo URL from the Github site, and edit it to replace your “local” details, e.g instead of
git clone git@github.com:timd/trashpanda.cc.git
you would need to edit this to
git clone git@github.personal:timd/trashpanda.cc.git
Once you’ve done this, all git commands work exactly the same as they did before, and you can basically forget about this entire process.
Using this process with an existing cloned repo
If you already have a repo locally, that’s not a problem - you can update the repo’s URL with the “new” value, for example:
git remote set-url origin git@github.personal:timd/trashpanda.cc.git
Pushes and pulls to this repo will now use the “new” settings and pick up the correct Github credentials.
Summary
This is about as fool-proof as it's possible to get in everyday use - at the cost of a bit of configuration and remembering to get the URLs right when cloning for the first time, you get a process which is transparent during the bulk of Git/Github workflows.
You could also argue that you get a more neatly-organised directory structure as a bonus, but moving projects around a filesystem is trivial by comparison with tweaking SSH configurations etc.