How I manage my work and personal GitHub accounts

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 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 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 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.

Things 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.

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.

Posted by Tom Limoncelli in Technical Tips

No TrackBacks

TrackBack URL: http://everythingsysadmin.com/cgi-bin/mt-tb.cgi/2080

2 Comments | Leave a comment

In terms of keeping home dirs in sync I migrated from svn to hg to vcsh (a git wrapper): https://github.com/RichiH/vcsh

Quite handy.

Tom,
I've had this issue too. There are a few ways to tackle it (as with any git issue :) ):

- Git 2.8 has a new command "git config --global user.useconfigonly true" which will force you to set your name and email per-repository. Unfortunately you can't do something like set your name globally and email locally. More info: git config --global user.useconfigonly true

- You could use Git Template (https://git-template.readthedocs.io/en/latest/) to define a pre-commit hook that checks if your email is set, and refuses the commit if it's not. Since you're setting a template, it would apply to any new git repo. Example for a pre-commit hook:

#!/bin/sh
#
# A git hook to make sure user.email exists before committing

EMAIL=$(git config user.email)

if [ -z "$EMAIL" ]; then
# user.email is empty
echo "ERROR: [pre-commit hook] Aborting commit because user.email is missing. Configure user.email for this repository by running: '$ git config user.email [email protected]'. Make sure not to configure globally and use the correct email."
exit 1
else
# user.email is not empty
exit 0
fi

Leave a comment

 
  • LISA16