How to Manage Multiple GitHub/GitLab/Bitbucket Accounts Using SSH Keys

~4 minute read

If you’ve used the Git command-line utility, you may have noticed that Git often needs user credentials to perform operations over HTTP, especially when the repository is private. It is possible to permanently store user credentials in Git credential storage to avoid entering them again and again, but this approach won’t work if you have to work on a remote repository which exists on another account. This gets even more complicated for systems with two-factor authentication, where the token you use for a password is randomly generated and unpronounceable.

We can solve this problem by using SSH (secure shell). SSH uses a pair of keys to initiate a secure handshake between remote parties. Also, it is more secure than password based authentication.

In this article, I’ll explain the steps to set up multiple accounts of Git based code hosting platforms — GitHub, GitLab, Bitbucket, etc — on a single machine. The approach I am about to describe relies on segregation of work belonging to different accounts into different directories, and editing the ~/.gitconfig file so Git can automatically recognize which directory belongs to which account. So, let’s get started!

1. Generate a new SSH Key Pair

You can generate a new SSH key pair using the below command on macOS, Linux and Windows:

$ ssh-keygen -t rsa -b 4096 -C "your_email@example.com" -f ~/.ssh/id_rsa_github_personal

If you’re on Windows, you have to run this command in Git Bash. And remember to provide a meaningful file name while generating the keys. If you don’t use the -f option, the program will prompt you to enter a file name. The above command will generate two keys:

  • Public key: ~/.ssh/id_rsa_github_personal.pub

  • Private key: ~/.ssh/id_rsa_github_personal

The public key is analogous to a physical lock which you share with the remote server to encrypt your data, and the private key is stored at a secure location in your file system which will later be used to “unlock” the protected data. The only difference is that SSH uses public key cryptographic algorithms (RSA, DSA) to perform these tasks.

2. Add SSH Public Key to Your Account

Share the public key (ending with.pub) with the remote server. Copy the contents of your public key to clipboard by opening the file in a text editor. Or you can copy it to clipboard directly from terminal like this:

  • macOS: pbcopy < ~/.ssh/id_rsa_github_personal.pub

  • Linux: xclip -sel clip < ~/.ssh/id_rsa_github_personal.pub

  • Windows (Git Bash): cat ~/.ssh/id_rsa_github_personal.pub | clip

Now paste your SSH public key into your account. On GitHub, the UI looks like this:

Add new SSH key on GitHub
Add new SSH key on GitHub

After pasting your public key into the text box above, click ‘Add SSH key’. You can follow these direct links to add a new SSH key into your account:

Follow the first two steps for all your personal and professional accounts, and remember to use a meaningful file name for your key (so you can recognize which key belongs to which account/website).

3. Edit gitconfig file

In this step, you have to edit the .gitconfig file. You will find this file here:

  • Linux and macOS: ~/.gitconfig

  • Windows: C:\Users\<username>\.gitconfig

Open the file in a text editor to define multiple one-to-one mapping between directories and the Git config file. Git has a [includeIf] directive which allows you to use a different configuration file if the specified condition evaluates to True. This directive was introduced in Git version 2.13.0, so check your version before going any further: git --version. Upgrade your Git client if required.

This is how my .gitconfig file looks like:

[user] name = Deepankar Sharma email = dash.srmk@gmail.com username = cquark7 [core] sshCommand = "ssh -i ~/.ssh/id_rsa_github_personal" [includeIf "gitdir:~/work/github"] path = ~/.gitconfig_github_work [includeIf "gitdir:~/work/gitlab"] path = ~/.gitconfig_gitlab [includeIf "gitdir:~/work/bitbucket"] path = ~/.gitconfig_bitbucket

Define the global (default) configuration in the beginning of the file. Set the path of your SSH private key using sshCommand variable. When this variable is set, git fetch and git push will use the specified command when they need to connect to a remote system. The global config will be used everywhere for performing Git operations, except when you’re present in a directory which matches the [includeIf] directive.

Create a separate Git config file for other accounts, and specify their filesystem path inside the [includeIf] directive. The config present inside this file will be used only when your present working directory matches the glob pattern specified after gitdir:. Read git-config documentation for more details.

This is how an example ~/.gitconfig_github_work file should look like:

[user] name = Your name email = work_email@example.com username = UserName [core] sshCommand = "ssh -i ~/.ssh/id_rsa_github_work"

Create a config file for all your accounts.

Now you can verify this setup by cloning a private repository, or by calling git config user.email inside existing repositories.

Note: [includeIf] conditional config only works inside git repositories. It won’t reflect any change within plain directories and uses global config as fallback.

Conclusion

This is it, guys! It’s nothing too complicated, and you no longer have to modify any config file manually while performing Git operations. Hope you found this useful! Please share your views and suggestions in the comment section below.