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 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 should reflect whether I am "Tom the person" or "Tom the employee". My work-related repos shouldn't be littered with my personal email address. It is ugly and, more importantly, it would mean that someone 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. Also, 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 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 that one machine will be only for work, and will have SSH keys associated with my work account. I would then have a different machine that I'd only use for personal stuff, and will have an SSH key there that is only associated with my personal account. 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 thing!
There is no such thing as
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 the filename points to the appropriate key.
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 defaults 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 remember to doctor the hostname. However I found that interfered with systems (usually install scripts) that didn't let me edit the hostname.
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.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
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.
I've found it greatly simplifies my life to have the exact same
~/.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.