Git config for multiple GitHub accounts
This post is for people who need to work on repositories owned by different GitHub accounts, for example their personal one and their “work account” part of their company’s team. Juggling authentication credentials can be annoying, but a few configuration options will make it much easier.
A typical setup: one account
One of the first steps when starting with Git is to configure your name and email. Git will in fact use them to sign all your commits and, if not set, it will try to guess them from your system environment and present you a warning.
If you host your code on GitHub setting your email address will be even more important, as GitHub uses emails to associate commits to user accounts.
This means that once you have this in your git config:
1 2 3 | git config --global -l user.email=myname@email.com user.name=My Name |
you’ll be able to commit, push, and then find your commit history on GitHub embellished with your avatar and with links to your profile page.
Another thing that a GitHub user has to decide is what kind of URL to use to reference a repository remote: either SSH or HTTPS.
It is arguably more secure and flexible to use a SSH URL rather than HTTPS, because a HTTPS URL:
- will require you to type your username and password everytime you push or fetch (yes, the same goes for private key passphrases, but they are less sensitive than your account password);
- the above can be avoided by using a credential helper to remember your password, which is a bad idea, especially if you’re using a laptop (what’s the point of having a password if anyone with access to your computer can bypass it?);
- it will not work if you have enabled two factor authentication anyway, or rather it will require you to setup an access token and use that to authenticate.
In addition to be (again, arguably) more secure, SSH references and authentication are easier to configure.
In my SSH tutorial I wrote on how to use a SSH config file to declare which private keys to use for which hosts. Since git will communicate with GitHub via SSH, we can use the ~/.ssh/config
file to configure this connections:
1 2 3 | Host github.com IdentityFile ~/.ssh/your_personal_github_private_key.id_rsa User git |
With that set, git is ready to automatically authenticate requests to GitHub. If your key has a passphrase (good!) it will prompt you to type it each time. There are ways to cache it, although the same considerations I made for the git credential helpers apply here.
What if we have multiple accounts
So far, we have described a fairly standard setup.
Things become a bit messier when you have work-related repositories on your personal computer and are accessing them with a different GitHub account that you use for work stuff.
This poses two challenges:
- Git should not sign your work commits with your personal email, otherwise GitHub will associate them to the wrong user account.
- When interacting with the remote (
git clone/push/fetch
) git should authenticate the requests with the work account, not the personal one.
How to handle multiple identities
The first problem is quite easy to solve.
All we need to do is to configure different name and email values only for the repositories associated to your alternative account, which can be done using the --local
flag instead of --global
.
In order to use git config --local
we need to be inside a repository directory: the keys will be written to the ./.git/config
file rather than ~/.gitconfig
(used when configuring with --global
). These config values will only apply to that specific repo, but they will also override any property already set at the higher --global
or --system
levels.
So, while the --local
configuration usually only contains repo-specific stuff like the remotes’ URLs or the branch names, we can execute this to add extra keys:
1 2 3 | cd repo_dir git config --local user.name "Name Surname" git config --local user.email "name.surname@company.com" |
The result will be the following snippet, which will ensure that a different email and name will be used to sign the commits in this repository:
1 2 3 4 5 6 7 | git config --global -l user.name=My Name user.email=myname@email.com git config --local -l user.name=Name Surname user.email=name.surname@company.com |
Problem #1 is solved.
How to handle multiple authentication credentials
This requires a few more changes, but nothing too difficult.
We’ve already seen how a repository’s remotes have URLs pointing to a server, for example:
1 2 3 | git remote -v origin git@github.com:account_name/repo_name.git (fetch) origin git@github.com:account_name/repo_name.git (push) |
We’ve also seen how, with that style of URLs, git will check the ~/.ssh/config
file to decide which private key to use.
With that in mind, the solutuon to problem #2 is to setup git to use a different SSH configuration for certain repositories.
Let’s start with the SSH config file, where we will add a new host alias:
1 2 3 4 5 6 7 8 | Host github.com IdentityFile ~/.ssh/your_personal_github_private_key.id_rsa User git Host work-github.com HostName github.com IdentityFile ~/.ssh/work/your_work_github_private_key.id_rsa User git |
The first group is what we already had.
The second one is interesting. work-github.com
is not a real domain name, we’re making it up, and for this reason we add the HostName
line to provide the actual domain name to use when the SSH agent will try to open a connection to the fake host alias. The effect is that SSH connections to github.com
will use the first configuration group, while connections to work-github.com
will use the second group but will still use the real GitHub URL.
Also notice how the second group references a different private key file, associated to another GitHub account: this will cause the SSH agent to authenticate to GitHub as a different user.
The next step is to update the remote’s URL in the repository:
1 2 3 4 5 | git remote set-url origin git@work-github.com:account_name/repo_name.git git remote -v origin git@work-github.com:account_name/repo_name.git (fetch) origin git@work-github.com:account_name/repo_name.git (push) |
That’s it. Now every time you will git push/fetch
or git remote prune origin
, git will open a SSH connection to the host alias, will use the special configuration in the SSH config file, and will actually connect to github.com
using the private key of your work account.
Working with your personal repositories will still work as it always has: the remotes’ URLs will still reference the real GitHub domain, and git will use the normal SSH configuration with your personal private key.
And what about cloning?
If you need to clone a new repository from the work GitHub organization, you can use the new host alias from the beginning to set up the remote’s URL automatically:
1 | git clone git@work-github.com:account_name/new_repo.git |
And if you’ve already set things up correctly, you will not need anything else.