github multiple users

Problem

A personal GitHub account and a work one, each with its own key and its own permissions. Sooner or later you push with the wrong identity, or you clone and get an authentication error that tells you nothing useful. The fix is to stop switching by hand and let the directory decide.

[email protected]: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights and the repository exists.

Looks familiar?

Initial Solution: .ssh/config

One approach to this problem is to use the SSH config file, located in the ~/.ssh/ directory. By configuring SSH aliases in this file, you can associate different keys with different hosts, effectively directing SSH to use a specific key for each GitHub account.

Here is an example of how you can set up your ~/.ssh/config:

# Personal GitHub account
Host github.com-personal
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_rsa_personal

# Work GitHub account
Host github.com-work
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_rsa_work

In this setup, github.com-personal and github.com-work are aliases that point to GitHub, each with a unique SSH key. When cloning or interacting with repositories, you’d use the alias corresponding to the right account. However, this method requires remembering to use the right host alias for each repository, which can get messy as the number of accounts and repositories grows.

There’s also an issue of dependencies. Often the URLs get mixed up when either NPM/Yarn or Go Vendor dependencies are at play. Attempted pulls from the configured aliases will not work outside of SSH.

Better Solution: .gitconfig

A cleaner solution lies in the utilization of Git’s powerful configuration system. Specifically, the .gitconfig file allows you to specify different users, keys, and settings for each workspace or directory.

You can set your global .gitconfig to include a different .gitconfig file based on the current directory. For example:

# ~/.gitconfig
[includeIf "gitdir:~/work/"]
  path = .gitconfig-work
[includeIf "gitdir:~/personal/"]
  path = .gitconfig-personal

Next, in each of these separate .gitconfig files, specify the user information for each account:

# ~/.gitconfig-work
[user]
  name = Work Name
  email = [email protected]

# ~/.gitconfig-personal
[user]
  name = Personal Name
  email = [email protected]

Now the directory decides the identity, which means you can’t forget to switch. That’s the whole appeal. Any workflow that depends on remembering something at the moment you’re least likely to be paying attention is going to fail eventually.