Use a different user account for each Git repo

#git #ssh

Written by Anders Marzi Tornblad

When you find yourself in a situation where you need to use different Git user accounts for different repositories, you should use `git config --local` to set the user name and email address. This is useful, for example, when you use the same computer for work-related repos and for your personal projects.

# Clone and configure a personal repo
git clone https://github.com/.....
cd personal-repo-dir
git config --local user.name 'Your Name'
git config --local user.email 'your.email.address@example.com'

cd ..

# Clone and configure a work repo
git clone https://github.com/.....
cd work-repo-dir
git config --local user.name 'Your Name'
git config --local user.email 'your.work.email@company.com'

This approach should be enough for most people, especially if you are using a credentials manager (which you really should). However, if you are using the SSH protocol to connect to your repositories (which you also should), you will need to use a different SSH key pair for each user account.

SSH protocol origin URLs

When you use the SSH protocol for synchronizing with your Git repositories, using a credentials manager and configuring your user information is not really enough. First of all, you will need to create a different SSH key pair for each of your user accounts. Then you need to decide which user account is the "main" one. Finally you need a way to use different SSH keys for each user account.

First, create two different SSH keys. In this example, I'm creating an RSA key for my work account, because we are using Azure DevOps for repository storage at work, and Azure DevOps doesn't yet (in October 2022) support the better ED25519 keys. I'm also creating an ED25519 key for my personal Github account.

# Create an RSA key pair for work account
ssh-keygen -f '~/.ssh/work-key' -b 4096

# Create an EDSCA key pair for personal account
ssh-keygen -f '~/.ssh/personal-key' -t edcsa -b 521

Second, copy the public keys to the SSH key settings for each of your user accounts. In Github, you do this in the SSH and PGP keys section in the user account settings. In Azure DevOps, the URL depends on your organization name, so I can't link to it directly, but open User settings, and then SSH public keys. Create a new key, paste your public key, and save.

Configuring the SSH command

To decide which SSH key to use for pulling and pushing, you need to configure the core.sshcommand setting of the git configuration for your repository. The difficult bit is that you can't do that before there is an initialized repository in a directory. But you need to use the correct SSH key to clone the repository, which makes this a bit of a Catch-22. Here are two examples of ways that will not work:

# This won't work, because git clone needs the SSH key before pulling
git clone git@...
cd repo-dir
git config --local core.sshcommand 'ssh -i ~/.ssh/personal-key -F /dev/null'

# This won't work either, because git config can only run inside a git repo dir
git config --local core.sshcommand 'ssh -i ~/.ssh/personal-key -F /dev/null'
git clone git@...

To use a specific SSH key when cloning a repository, you need to do some of the plumbing yourself. This is how I do it:

# First create a directory and initialize it
mkdir repo-dir
cd repo-dir
git init

# Configure the SSH command
git config --local core.sshcommand 'ssh -i ~/.ssh/personal-key -F /dev/null'

# Add the origin URL
git remote add origin 'git@.....'

# Pull the code
git pull origin main

Bash script for cloning

Finally, you can put this all together in a bash script that sets the correct user name and email, configures the correct SSH command, and pulls a repository. This is the current version of the script that I use:

#!/usr/bin/bash
# Script to clone repositories from my personal github account
# 
# USAGE:
# ./clone.sh DIRNAME SSH-GITHUB-URL
# 
# EXAMPLE:
# ./clone.sh some-repo git@github.com:atornblad/some-repo.git

mkdir "$1"
cd "$1"
git init

git config --local core.sshcommand 'ssh -i ~/.ssh/personal_key -F /dev/null'
git config --local user.name 'Anders Marzi Tornblad'
git config --local user.email 'my.email.address@example.com'
git config --local push.autosetupremotes true
git remote add origin "$2"
git pull origin main