The 2022 Stack Overflow Developer Survey shows that 93.78% of developers are using Git as their version control system. This may not come as a shock since just about every developer I know uses Git as their primary version control system. SVN and Mercurial are now hosting that one piece of software that everybody is too scared to touch and only one developer in the basement still knows how to use.

We’ll just gloss over the 4.31% of respondents who don’t use version control…

With Git being so dominant you’re bound to bash your head against this one tiny little issues related to SSH connections. I have multiple Git based accounts that I use regularly.

  • 1 x Work Gitlab Account
  • 1 x personal Gitlab Account.
  • 1 x “hobby” Gitlab account.
  • 1 x Personal Github Account.

Each Gitlab Account requires a unique SSH key. Each Gitlab account is linked to a unique email address. My Github account can reuse one of the SSH keys but requires I remove my email from commits 🫠

This presents a problem because by default, Git will just use a single .gitconfig for the credentials and your primary SSH key which is probably ~/.ssh/id_rsa.

Fortunately Git can support multiple configurations with a bit of tweaking. Let’s assume that you’ve used the same home directory layout I have.

.
├── personal
│   ├── github
│   ├── gitlab
│   └── hobby
└── work

Create a .gitconfig in home that has all your default credentials. Since I primarily use this setup for work, that is my default. My .gitconfig is below. There is probably a lot more in your .gitconfig but the important stuff is the includeIf sections.

[user]
  name = First Last
  # Don't set email here

## This is the important stuff
[includeIf "gitdir:~/work/"]
  path = ~/work/.gitconfig.work

[includeIf "gitdir:~/personal/github/"]
  path = ~/personal/.gitconfig.github

[includeIf "gitdir:~/personal/hobby/"]
  path = ~/personal/.gitconfig.hobby

[includeIf "gitdir:~/personal/gitlab/"]
  path = ~/personal/.gitconfig.gitlab

The includeIf uses a basic regex to see if you are executing the git command for a directory that matches the if statement. If it does match, it will then include the path specified and merge/override settings.

You then need to create those files, your directory structure should look like this afterwards:

.
├── .gitconfig
├── personal
│   ├── .gitconfig.github
│   ├── .gitconfig.gitlab
│   ├── .gitconfig.hobby
│   ├── github
│   ├── gitlab
│   └── hobby
└── work
    └── .gitconfig.work

Now you can customise each file to match your requirements. For Gitlab, I need to override the sshCommand to use my personal Gitlab SSH key:


[user]
  name = First Last
  email = personal-email@gmail.com

[core]
  sshCommand = "ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_gitlab_personal"

As I said earlier, because Github requires an anonymised email and uses my primary SSH key, I only need to overwrite the email.


[user]
  name = First Last
  email = some-user@users.noreply.github.com

Repeat this for each .gitconfig.x file. If you haven’t done so already, create your unique ssh key per target environment and be sure to clone repositories in to the right folders. If you have existing repositories just move them to the correct subfolder.

There is also a quick way to test and make sure it is working before trying to clone or push code. Change to a directory that is not using the default settings and use the git config --get command. The way the includeIf is written, you must change to a directory 1 level deeper than the path used for the regex. Using same layout as before, it will be the test-in-here directory.

.
├── personal
│   ├── github
│   ├── gitlab
│   │   └── test-in-here
│   └── hobby
└── work

Run this command

$ git config --get core.sshCommand

If it works you should see your custom sshCommand listed

ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_gitlab_personal

If you want to see all your settings run

git config --list