Multi-Git-Account-Mastery

managing SSH Keys: A (Wacky) Solution for Multiple GitHub Accounts

Author

Joost de Theije + LLM

Published

April 23, 2024

Abstract
Streamline Your Git Workflow. Manage multiple GitHub accounts and SSH keys using custom .gitconfig files. Learn how to configure global Git settings, include specific configuration files, and remap hostnames in your SSH config file. Automate your git workflow and say farewell to fiddeling around with SSH and GPG keys.

1 Git

Git, everyone’s favorite version control system, was released (checks notes) 19 years ago on April 7th, 2005. That is some time ago.

Currently, every developer uses Git for one or more projects and/or organizations. In modern days, each and every repo/organization has some form of authentication or other requirements to work with it. I have seen some pretty wacky setups to control how Git is being configured in order to streamline developer productivity and security.


And now, I will introduce my wacky solution 😜 for handeling ssh keys for multiple github accounts.

1.1 Basic Structure

The structure I use has the following files:

  • .gitconfig
  • .gitconfig_github_personal
  • ~/.ssh/config

1.1.1 .gitconfig

[user]
useConfigOnly = true

[includeIf "gitdir:~/Developer/github_personal/"]
path = ~/.gitconfig_github_personal

1.1.2 .gitconfig_github_personal

[user]
name = personal_name
email = personal_email@example.com

1.1.3 ~/.ssh/config

Host github.com
  HostName github.com
  User personal_name
  IdentityFile ~/.ssh/personal_key

So far, not too whacky, right? Git uses the .gitconfig file to configure Git globally, and then only the actions performed in the folder ~/Developer/github_personal/ will use the .gitconfig_github_personal file. The SSH key is defined in the SSH config and is used solely for GitHub connections.

Now, if you make a commit, the name and email from the .gitconfig_github_personal are attached to that commit. This is all fun and games, but what if another project requires a Bitbucket or GitLab account? You can create a .gitconfig file for each service and add the right key settings to the SSH file.

The “fun” starts when there’s a second instance of a GitHub account; now, all of a sudden, you have a collision in the way you handle your SSH keys - they have the same hostname. 😩

1.2 Extending the Structure

lets add a additional gitconfig for the work github

  • .gitconfig
  • .gitconfig_github_personal
  • .gitconfig_github_work
  • .ssh/config

1.2.1 .gitconfig

[user]
    useConfigOnly = true

[includeIf "gitdir:~/Developer/github_personal/"]
    path = ~/.gitconfig_github_personal

[includeIf "gitdir:~/Developer/github_work/"]
    path = ~/.gitconfig_github_work

adding one line for the new work directory, this is linked to the new work gitconfig file.

1.2.2 .gitconfig_github_work

[user]
    name=work_name
    email= work@example.com

[url "git@github.com-work"]
    insteadOf = git@github.com

this is where the magic happens, we instruct git to modify the URL it uses to connect to GitHub, and in the SSH config file, we remap this to the correct hostname. The result is that we can clone repositories as normal, and the folder location determines which SSH keys are used. This means that once set up, we can get on with our work instead of fiddling around with SSH keys. Automation wins!

1.2.3 .ssh/config

Host github.com
  Hostname github.com
  User personal_name
  IdentityFile ~/.ssh/personal_key

Host github.com-work
  Hostname github.com
  User work_name
  IdentityFile ~/.ssh/work_key

1.3 Bonus GPG Signing

If you want to be able to sign commits (and get a green checkmark next to your commits) you can extend the above structure to utilize the SSH key for Git commit signing.

1.3.1 .gitconfig

[user]
  useConfigOnly = true

[gpg]
  format = ssh

[includeIf "gitdir:~/Developer/github_personal/"]
  path = ~/.gitconfig_github_personal

[includeIf "gitdir:~/Developer/github_work/"]
  path = ~/.gitconfig_github_work

We start with the global Git config and define the GPG format to be SSH.

1.3.2 gitconfig_github_work

[user]
  name = work_name
  email = work@example.com
  signingkey = <your ssh key>

[commit]
  gpgsign = true

[url "git@github.com/work"]
  insteadOf = git@github.com

Here, I have added the signingkey option for the user and set the gpgsign indicator to true.

Now also add your ssh key as a signing key!

The next time you commit, it is signed with your SSH key 100% automatically and pain-free – how cool is that!!

Signed Commit

P.S. You can also attend a GPG signing party but that’s a topic for another time.