Managing Multiple Git Accounts on a single machine
Tags: git, ssh, github, tutorial
Published: 2023-07-15 18:44:19

## Introduction

Suppose you want to work with git repositories whose remotes are authenticated with different user accounts.  Maybe you have work and personal GitHub accounts, or you work with repositories from multiple hosting services like GitLab or Sourcehut.

The simplest solution is to clone the repositories using HTTPS (instead of SSH). But who wants to enter a username and password for every authenticated command? This post will demonstrate an SSH-based configuration for seamless operations.

Ready?  Let's get into it.

### Prerequisites
Your remote git accounts (e.g. with GitHub or GitLab) are configured for SSH authentication, and your machine is configured for SSH authentication with one of these accounts.

If not, refer to [GitHub's website for setup instructions](https://docs.github.com/en/authentication/connecting-to-github-with-ssh), or the instructions provided by the hosting service of your choice.

## SSH Key Setup
SSH keys are stored in `~/.ssh/` as public/private key pairs. By default the files are named after the encryption algorithm; for RSA you will find:

```sh
id_rsa
id_rsa.pub
```

or for ed25519:
```sh
id_ed25519
id_ed25519.pub
```

Copy the second pair of keys you wish to authenticate with to `~/.ssh/`. Give them a unique name to set them apart from the first pair, e.g.:

```sh
id_rsa -> id_rsa_gitlab
id_rsa.pub -> id_rsa_gitlab.pub
```

Set correct file permissions for private and public key files:
```sh
chmod 600 id_rsa_gitlab # only owner can read/write
chmod 644 id_rsa_gitlab.pub # owner can read/write, everyone else can read
```

## Git Configuration at Repository Level
This setup is the simplest method.

```sh
git config core.sshCommand "ssh -o IdentitiesOnly=yes -i ~/.ssh/id_rsa_gitlab -F /dev/null"
```

If you only require alternate authentication with a few repositories, this may be good enough.  But if you want a single configuration that works across all repos in your user environment, continue reading below.

## SSH Config Entry

To make this work with a single configuration in your user environment, we will use the SSH config.

Make SSH aware of the additional keys by editing `~/.ssh/config`.

If the file doesn't exist create it first:
```sh
touch ~/.ssh/config
chmod 600 ~/.ssh/config
```

Add `Host` entries to the file:
```
# GitHub account
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa

# GitLab account
Host gitlab.com
HostName gitlab.com
User git
IdentityFile ~/.ssh/id_rsa_gitlab
```

When performing SSH authentication, the correct keys are determined by matching the config entry with the user and host names in the repository's remote URL.

To confirm an existing repository is configured to use SSH check the remote origin URL:
```sh
git remote -v
```

To change the remote URL run the command:
```sh
git remote set-url origin git@github.com:<user>/<repository>.git
```

To do this with a new repository clone with the SSH - not HTTPS - URL:
```sh
git clone git@github.com:<user>/<repository>.git
```

For example:
```sh
git clone git@github.com:bruc3mackenzi3/go-microservice-template.git
```

### Entries for the Same Host

The example above will not work if both accounts are with the same host.  For this a _host alias_ is required:
```
# Work GitHub account
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa

# Personal GitHub account
Host github.com_personal
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa
```

`github.com_personal` is just an alias, anything will work here.

Now, with one of the commands provided above, clone or edit the remote origin URL to use the alias.  E.g.:

```sh
git@github.com_personal:bruc3mackenzi3/go-microservice-template.git
```

## Optional - Configure User Name and Email

It's also a good idea to set the user name and email for the repository. Even though this isn't used in the authentication process, this information shows up in commits and is used by GitHub to associate with a user account. Since you're reading this article, chances are your global Git configuration is set to another account.

Before changing, you can check the current value by running:
```sh
git config user.email
```

To set a different email:
```sh
git config user.email <your-github-account-email>
```

Note this sets `user.email` in the repository configration file, `.git/config`. If you saw a different email prior, chances are it was set in the global configuration and is still present. It is this email that will continue to be used in other repositories, unless they also overwrite the global `user.email` value with their own configuration.

You can confirm this by getting all values for an option:
```sh
git config --get-all user.email
```

Repeat the same for username with the same commands, by replacing `user.email` with `user.name`

4. Verifying the configuration works
To verify the setup is working, we need to perform a git operation that requires priveledged access to a repository. If you went with the cloning option in section #3, and that repo is private then you've already confirmed it's working! Another way to verify is by pushing a new branch:

```sh
git checkout -b test-ssh-config
git push --set-upstream origin test-ssh-config
```

## Conclusion

To explore this topic further, you can check out [GitHub documentation on managing multiple accounts](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-personal-account-on-github/managing-your-personal-account/managing-multiple-accounts).

Thank you for checking out this post on improving development workflows with git repositories from different user accounts.  I hope you find this configuration handy in creating a more seamless development experience.  Happy `git push`'ing!