Using Multiple GitHub Accounts
The Problem
You have multiple GitHub accounts, and you want git to automatically use the "right" GitHub account.
A good way to do that is to put work-related stuff under a single directory,
say, ~/Work
. Then, configure git to use your work account for any project
in your ~/Work
directory.
In this article I set things up so that:
- Projects in
~/Work/
use your work GitHub account - Projects elsewhere use your home GitHub account
My git configuration on GitHub is generated from this article.
The SSH Config
Assuming you use the git
protocol to clone repositories (not https
), you
must create at least two SSH keys for GitHub – one for each GitHub account
(GitHub will not allow you to use the same SSH key for both accounts, but
will allow you to use the PGP key for both accounts).
Once you've created your SSH keys, your ~/.ssh
directory will look something
like:
$ tree ~/.ssh/ /Users/cfclrk/.ssh/ ├── config ├── github-home ├── github-home.pub ├── github-work └── github-work.pub
Ensure these SSH keys work:
ssh -i ~/.ssh/github-home -T git@github.com 2>&1
ssh -i ~/.ssh/github-work -T git@github.com 2>&1
We don't need to modify the ~/.ssh/config
file. Instead, we'll explicitly
tell git which SSH keys to use in our git config files.
The Git Config
Here we tell git to use different git configurations for different
directories. Git supports this with the includeIf
directive (read about it
here). Do this by creating the following two files:
~/.config/git/config
[user] name = Chris Clark email = cfclrk@gmail.com signingkey = C6ECD046467701AB [core] sshCommand = "ssh -i ~/.ssh/github-home" [commit] gpgsign = true [init] defaultBranch = main [github] user = cfclrk [includeIf "gitdir:~/Work/"] path = work.gitconfig
~/.config/git/work.gitconfig
[user] email = cclark@splashfinancial.com [core] sshCommand = "ssh -i ~/.ssh/github-work" [github] user = cclark-splash
Ignore the [github]
sections; those are for Emacs forge. And of course,
update the values for your name
, email
, and – if you're using
Signed Commits – your PGP signingkey
id.
That's it for the git config! Move on to Signed Commits. The next subsection explains the above, if you are interested.
More about Git Config Loading
Git loads all applicable config files. If one option is set multiple times (potentially form differnt files), the last value wins.
For example: assume you have the git config files above, which has:
[includeIf "gitdir:~/Work/"] path = work.gitconfig
Now, when you run a git command in a project located at ~/Work/projectA/
,
git does something like:
- Load the default
~/.config/git/config
file- Set
core.sshCommand
tossh -i ~/.ssh/github-home
- Set
- Does
[includeIf "gitdir:~/Work/"]
apply?- Yes! Load the work.gitconfig file
- Set
core.sshCommand
tossh -i ~/.ssh/github-work
In this case, both config files were loaded. The value of core.sshCommand
is ssh -i ~/.ssh/github-work
, because that value was loaded last.
The determining factor is the order in which the configuration is defined, and the last value wins.
Signed Commits
Rationale
Why sign commits?
The value of user.email
is the only piece of information GitHub uses when
determining what profile picture to display next to a commit. You can set that
email address to anything! E.g. set it to torvalds@linux-foundation.org
, and
GitHub will happily put Linus Torvalds' picture next to your git commits. And
to be sure, that happens.
If you don't want other people impersonating you, you can partially mitigate this problem of attribution by using signed commits.
GitHub allows you to upload a PGP key to your GitHub account, and GitHub
displays a "Verified" badge on commits that proprely verify (i.e. git
verify-commit <commit>
works). For a commit to verify,
- The email address in the commit must match your GitHub account email address
- The commit must be signed by a PGP key that has been uploaded to your GitHub account
Prerequisites
First install the necessary tools:
brew install gnupg brew install pinentry-mac
pinentry-mac
saves passphrases in the MacOS keychain.
Create PGP key
Although GitHub has some instructions for creating a PGP key, I find it easier to use keybase.
To use keybase, first install the native app (this installs the keybase
CLI
program).
You can import preexisting PGP keys from keybase, but it's a better idea to create a new PGP key for every device. To view your existing PGP keys in keybase:
keybase pgp list
And to list your local PGP keys (this may be empty):
gpg --list-secret-keys --keyid-format=long
Now, create one new PGP key. We'll add both your home and work email addresses to this key, then upload the public key to both GitHub accounts (GitHub will allow the same PGP key to be used for multiple accounts). Alternatively, you could create two different PGP keys: one for each GitHub account.
keybase pgp gen --multi
- It will prompt you for email addresses one at a time. Add both your home and work email addresses.
- Add a passphrase.
Update trust level
Update this key's trust level to "ultimate"; this is not strictly necessary,
but will make some gpg
CLI output cleaner.
gpg --edit-key $keyid
At the prompt, type trust
, after which you'll see some output like this:
Please decide how far you trust this user to correctly verify other users' keys (by looking at passports, checking fingerprints from different sources, etc.) 1 = I don't know or won't say 2 = I do NOT trust 3 = I trust marginally 4 = I trust fully 5 = I trust ultimately m = back to the main menu
Choose 5
for ultimate trust. Then, at the prompt, type save
.
Add key ID to git config
Get the GPG key ID of your PGP key. To get the key ID:
gpg --list-secret-keys --keyid-format=long
In the above, the key ID is 80027A20FC0B6207
(is there some command that
prints out the key id?). Update your git config like so:
[user] signingkey = 80027A20FC0B6207 [commit] gpgsign = true
Update gpg-agent.conf
Add the following to ~/.gnupg/gpg-agent.conf
. This allows for automatic
signing (on MacOS anyway).
# Connects gpg-agent to the MacOS keychain. This enables # automatic key signing. pinentry-program /opt/homebrew/bin/pinentry-mac
Make a git commit
If you used a passphrase on your PGP key, your first git commit will probably fail. For your first git commit:
export GPG_TTY=$(tty)
Now, when you make a git commit, it should prompt you for the PGP key's passphrase. After you do this once, you should never have to do it again.
Add public key to GitHub
TODO: keybase pgp export $keyid
and gpg --armor --export $keyid
create
different things. Do they both work? Which is more appropriate to put in
GitHub?
gpg --armor --export $keyid | pbcopy
Add this key to GitHub.