| English | 中文 |
My company team uses GitLab to host code, while I also have personal repositories on GitHub. Since my work email and personal email are different, the SSH keys generated from them are also different — which creates a conflict. This article provides a solution to this problem: how to use both GitHub and GitLab on the same machine.
When you use the ssh protocol or git protocol to push to a remote repository via terminal commands, the process roughly goes like this (assuming you have already configured your local SSH Public Key on GitHub):
~/.ssh/authorized_keys on Linux) and verifies its access permissions.For more on SSH, see SSH Principle Introduction. For a more accessible read, see Ruan Yifeng - SSH Principles and Usage (Part 1): Remote Login.
Regardless of which hosting provider you use, Git identifies users solely by email address. When you use different providers with different emails, the SSH keys generated from those emails will naturally differ. When you try to push between providers, Git doesn’t know which SSH key to use, which causes the push to fail. Common scenarios include:
xirong.liu@corp.xx.com, and personal GitHub with ixirong.liu@gmail.com (the same applies to Bitbucket).Since email is the sole means of identification, the simplest approach is to use the same email for both. This produces the same public key, which you upload to both GitHub and GitLab. Then set a global Git config: git config --global user.name 'xirong.liu' && git config --global user.email 'xirong.liu@corp.xx.com'. This works fine for day-to-day development.
In practice, using the same email for both isn’t always feasible, which leads us to Option 2.
Option 2 works by configuring an SSH config file that tells SSH to use different authentication keys for different hostnames.
Git includes a tool called git config that lets you get and set configuration variables, which control how Git looks and behaves. These variables can be stored in three different locations:
/etc/gitconfig — Contains values for every user on the system and all their repositories. Pass --system to git config to explicitly read from and write to this file.~/.gitconfig — Specific to your user. Pass --global to make Git read from or write to this file.config file inside a Git directory (i.e., .git/config) — Specific to that single repository, regardless of which one you’re currently using. Each level overrides the one above it, so values in .git/config override those in /etc/gitconfig. Pass --local to make Git read from or write to this file.Since we’re using different emails for different providers, the commonly used git config --global is no longer sufficient — you must configure your username and email in each repository’s directory. (Don’t want the hassle? Here’s how xirong handles it: since there are more personal GitHub repos than work repos, the global config is set to the personal email with git config --global user.email 'ixirong.liu@gmail.com', and the work email is configured only in each team project directory.)
As described above, xirong’s setup looks like this:
# Global config — used by default for GitHub repositories
git config --global user.name 'xirong' && git config --global user.email 'ixirong.liu@gmail.com'
# Team project config — run this each time a new project is created
git config --local user.name 'xirong.liu' && git config --local user.email 'xirong.liu@corp.example.com'
By default, SSH keys are saved under ~/.ssh/, with the default filenames id_rsa and id_rsa.pub. Since we need separate keys, do the following:
# Generate a key with a custom filename for GitLab
ssh-keygen -t rsa -f ~/.ssh/id_rsa.gitlab -C "xirong.liu@corp.example.com"
# Generate the default key for GitHub
ssh-keygen -t rsa -C "ixirong.liu@gmail.com"
After running these commands, two new files — id_rsa.gitlab and id_rsa.gitlab.pub — will appear in ~/.ssh/. The contents of id_rsa.gitlab.pub are the key you’ll upload to GitLab.
In the ~/.ssh directory, create the config file if it doesn’t already exist with touch ~/.ssh/config, then add the following:
Host corp.example.com
HostName git.corp.example.com
IdentityFile ~/.ssh/id_rsa.gitlab
User xirong.liu
Host parameter matches the hostname given on the command line. For example, with ssh -T git@corp.example.com, the host is corp.example.com.Host matches will SSH translate git@corp.example.com into git.corp.example.com.Host does not support mixing wildcards with hostnames (e.g., *.example.com); a standalone * matches all hosts and acts as a catch-all default rule.HostName is required — fill it in based on the actual hostname used in your commands.Once configured, any Git repository matching git.corp.example.com will use the ~/.ssh/id_rsa.gitlab key for authentication; all others will use the default.
Using GitHub as an example:
In the form that appears, give the key a name of your choice, then paste the contents of ~/.ssh/id_rsa.pub into the key field, and click Add key.
GitHub will prompt you to enter your password once to confirm. The process for GitLab is the same — go ahead and do it yourself.
Each hosting provider has a unique SSH endpoint. For GitHub it’s git@github.com:*. You can test your setup like this:
➜ ~ ssh -T git@github.com
Hi xirong! You've successfully authenticated, but GitHub does not provide shell access.
➜ ~ ssh -T git@gitlab.dev
Welcome to GitLab, xirong.liu!
If you see these Welcome messages, you’re good to go.
This same approach works for any additional hosting providers you need to add. Here’s a look at xirong’s ~/.ssh directory with multiple providers configured:
➜ ~ ll ~/.ssh
total 40
-rw-r--r-- 1 xirong staff 264 Jul 10 14:42 config
-rw------- 1 xirong staff 3243 Jul 10 14:09 id_rsa
-rw------- 1 xirong staff 1675 Jan 28 20:39 id_rsa.gitlab
-rw-r--r-- 1 xirong staff 407 Jan 28 20:39 id_rsa.gitlab.pub
-rw-r--r-- 1 xirong staff 747 Jul 10 14:09 id_rsa.pub
-rw------- 1 xirong staff 1679 Jun 22 11:42 id_rsa_gitcafe
-rw-r--r-- 1 xirong staff 407 Jun 22 11:42 id_rsa_gitcafe.pub
-rw-r--r-- 1 xirong staff 9139 Jul 29 15:08 known_hosts