I have two accounts on GitHub: Personal and work. How do I access both from the same computer without getting them confused? I have two different ssh keys and use .ssh/config
to do the right thing. Some bash aliases also help.
Why?
Why is it important to me that I keep these two accounts separate?
First, certain repos can only be accessed from one account or the other. Public repos can be accessed from either, but private repos are not so lucky.
Second, I want the commit logs for different projects to reflect whether I am "Tom the person" or "Tom the employee". My work-related repos shouldn't be littered with my personal email address. That would be ugly and, more importantly, it would mean that a coworker searching for my commits would have to do two searches: one for each of my names. My username is different at my work account ("tlimoncelli" vs. "tal")... how could I expect a coworker to know that?
Lastly, when I contribute to a third-party project it is a very intentional decision whether I am contributing as a StackOverflow employee or as myself. I want bug reports and other notifications sent to one email address or the other depending on the situation. This future-proofs things so that when I change jobs (no current plans, BTW), I'll stop receiving notifications from projects that I'm involved in for purely work-related reasons.
What doesn't work?
You can't upload the same SSH public key to GitHub two accounts. GitHub uses the key to determine which account you are accessing, so they must be unique. If you were able to upload the same key to both accounts, GitHub would have to guess your intention for each repo, and that guess would often be wrong. You can upload multiple keys to each account, but there may not be overlapping keys between the accounts.
I could simply decide to have two separate machines, a work machine and a personal machine, each with different SSH keys. However then I would have to switch machines when I want to change which project I'm contributing to. However, expecting me to carry around 2 laptops is silly. That isn't to say that some companies should adopt such a policy, especially ones that have higher security requirements, but that's not my situation.
What do I do?
I set up a fake hostname in .ssh/config
to indicate which SSH key to use.
Here's an example:
git clone [email protected]:StackExchange/httpunit.git
git clone [email protected]:StackExchange/httpunit.git
^^^^^^^^^^^^^^^ What??? That's not a machine!
There is no such machine as home-github.com
or work-github.com
. However, if you look at my .ssh/config
file you'll find a "Host" entry that sets the actual hostname and sets a bunch of parameters, including which SSH key to use:
# Personal GitHub account:
Host home-github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519-homegithub
PreferredAuthentications publickey
PasswordAuthentication no
IdentitiesOnly yes
# Work GitHub account:
Host work-github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519-workgithub
PreferredAuthentications publickey
PasswordAuthentication no
IdentitiesOnly yes
On any machine that I use git, I simply make sure that SSH keys specified by the two different IdentityFile
s exist.
When someone gives me an SSH-based Git URL, I manually doctor the hostname by adding the "home-" or "work-" prefix. After that, everything just works.
If I forget to edit the hostname, I have a default set so that it uses my work key. Originally I set it up so that using the undoctored hostname fails. That way I'd get an error and I'm forced to remember to doctor the hostname. However I found that interfered with systems (usually install scripts) that didn't let me edit the hostname.
Commands like go get
are unaffected by this system since they use anonymous HTTP, not Git.
Setting the user.email correctly
The other problem I had was properly configuration git user.name
and user.email
. My global ~/.gitconfig
file sets user.name
because I am always Tom Limoncelli. However, I leave user.email
unset in that file to force me to set it per-repo.
I've set up Bash aliases to let me easily set the email address:
alias gitmeHome='git config user.email [email protected]`
alias gitmeWork='git config user.email [email protected]`
After I do "get clone", I need to remember to cd
into that repo and run either gitmeHome
or gitmeWork
. If I forget, I get this nice reminder:
$ git commit filename
[master 5667341] yes
Committer: Tom Limoncelli <[email protected]>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:
git config --global user.name "Your Name"
git config --global user.email [email protected]
After doing this, you may fix the identity used for this commit with:
git commit --amend --reset-author
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 dirname/filename
By having the bash aliases, setting user.email
is without hassle.
One more thing.
This last bit of advice isn't required to make ssh keys work, but I find it useful.
I've found it greatly simplifies my life to have the exact same ~/.ssh/config
and ~/.gitconfig
file on all my machines.
Manually adding a new Host entry to ~/.ssh/config
on the proper machines is a pain. It is easier to copy the entire master file (which I keep in git, of course) is easier. If a particular machine doesn't need that Host entry, who cares? Either I won't use it, or it will fail if I do use it. My Host entries are carefully constructed so that they work if the right keys are on the machine, and fail otherwise.
Having the same ~/.gitconfig
on all my machines is a little more tricky. It contains the settings that are the same everywhere. Overrides are set in the repo-specific .git/config
file. As you saw above, a setting like user.email
is critical, so I have no default in the global file thus the per-repo setting is required.