Managing Multiple Git Accounts Like a Pro

Table of Contents

Managing multiple SSH keys for connecting to different account on various git repositories hosting platform (eg. Github, Bitbucket or Gitlab) is very hard trust me. For each project you have to choose which SSH key you want to use and then enter email/password is too much.

First of all you can just use one SSH key for everything, SSH keys are used to verifying your identify. But make sure you have a different SSH key for each of your device (easier to decommission the device)

Problem statment

I am trying to commit to different accounts in Github from the same machine. I had two SSH keys for each account. It was hell.

Right now, I don’t need to think about anything.

Solution

Switching accounts on Github

You can switch between two accounts on Github

  1. Click on the profile icon
  2. Click on Add Account to add your secondary account

Now you can switch between both profiles easily

Github Switch Account

1. Setup for different profiles

Lets assume you want have two profiles on Github one for personal and one for work

In order to use two profiles, you need to create two main directories, one for personal and one for work. Now keep in mind to clone/create repos accordingly. Personal repos must go into personal folder and similarly for work repos

2. Generate SSH keys

ssh-keygen -t ed25519 -C "your_personal_email@example.com" -f ~/.ssh/<personal_key> 

You can optionally add a passphrase

ED25519 are recommended for security and performance, but RSA with a sufficient length is also a valid alternative:

ssh-keygen -t rsa -b 4096 -C "your_personal_email@example.com" -f ~/.ssh/<personal_key> 

-C is for adding a comment, it can be anything but it will be helpful to know the email associated with your account
-f is to define a filename, and creating a key with a descriptive name will help you remember which key is used for which user/remote

Do this for you work mail

ssh-keygen -t ed25519 -C "your_personal_email@example.com" -f ~/.ssh/<work_key> 

To update the passphrase for your SSH keys:

ssh-keygen -p -f ~/.ssh/<private_key>

3. Adding the SSH Keys

Now we need to add those keys we created to our system.

First let’s start the SSH agent

eval "$(ssh-agent -s)"

and then

ssh-add -K ~/.ssh/<personal_key>
ssh-add -K ~/.ssh/<work_key>

The -K flag in ssh-add is specific to macOS, and it adds the passphrase of the private key to the keychain. This means that once you’ve added the key to the keychain, you won’t be asked for the passphrase again when using the key.

4. Edit you SSH config

If you don’t have a SSH config inside ~/.ssh, then create one using touch ~/.ssh/config

Edit it to the following

Host personal
  HostName github.com
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/<personal_key>

Host work
  HostName github.com
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/<work_key>

5. Add public keys to hosts

We will add the public key part of our keys to the right profiles on Github

To copy public key of the generated keys use this

 pbcopy < ~/.ssh/<personal_key>.pub

or just output it and copy it

cat ~/.ssh/<personal_key>.pub

To add the public key part go here. Select Authentication Key and give a suitable Title.

Additionally if you want to sign your commits add the same public part again but this time as a Signing Key

6. Updating your gitconfigs

This is the most crucial part. We will be making custom .gitconfig for each of our profile

Create dotfile inside each of those folders we created earlier, you can give any suitable name to those dotfile

This is how the final file structure should look like

/<some_folder>/
|__work/
    |_.gitconfig-work
|__personal/
    |_.gitconfig-personal

Now, copy these to the dotfiles and fill properly the values. If you are not signing key then remove it form the config.

# ~/<path_to_personal_folder>/.gitconfig.pers
 
[user]
	email = your_personal_email@example.com
	name = Your Name
	signingkey = ~/.ssh/<personal_key>.pub
 
 
[core]
	sshCommand = "ssh -i ~/.ssh/<personal_key>"
# ~/<path_to_work_folder>/.gitconfig.work
 
[user]
	email = your_work_email@google.com
	name = Your Name
	signingkey = ~/.ssh/<work_key>.pub

 
[core]
	sshCommand = "ssh -i ~/.ssh/<work_key>"

Here we tell Git which key to use by making explicit the SSH command (the -i option is for specifying an identity file or key). This gives us more control, for instance, imagine you have multiple accounts, if you were using the SSH config file to use different SSH keys, you would need to create and remember an arbitrary prefix like first.github.com and then remember to use that domain each time you want to clone a repository with this account. This can be too much trouble.

7. Global Config Update

This is the magic part

Updating your global .gitconfig, which is present at ~/.gitconfig , i.e the home directory

[init]
	defaultBranch = main

[gpg]
	format = ssh

[commit]
	gpgsign = true
		
[includeIf "gitdir:~/<path_to_work_folder>/"]
    path = ~/<path_to_work_folder>/.gitconfig-work

[includeIf "gitdir:~/<path_to_personal_folder>/"]
    path = ~/<path_to_work_folder>/.gitconfig-personal

[core]
	excludesfile = ~/.gitignore 
[init]
  defaultBranch = main
  • When you run git init, the default branch will be named main instead of the older default master.
[gpg]
  format = ssh
  • Tells Git to use SSH keys for GPG signing commits/tags.
[commit]
  gpgsign = true
  • Enables GPG/SSH signing for all commits by default. Ensures commit authenticity.
[includeIf "gitdir:~/<path_to_work_folder>/"]
  path = ~/<path_to_work_folder>/.gitconfig-work
  • If a Git repo exists inside <path_to_work_folder>, Git will include settings from .gitconfig-work file for that repo.
[includeIf "gitdir:~/<path_to_personal_folder>/"]
  path = ~/<path_to_personal_folder>/.gitconfig-personal
  • Similar to above, but for personal projects.
[core]
  excludesfile = ~/.gitignore
  • Specifies a global .gitignore file. Patterns in ~/.gitignore will be ignored by all repos.

Single Profile

If you just want to setup just a single account on Github then follow till Step 5, the update your global .gitconfig as follows

[init]
	defaultBranch = main

[gpg]
	format = ssh

[commit]
	gpgsign = true
 
[user]
	email = your_personal_email@google.com
	name = Your Name
	signingkey = ~/.ssh/<personal_key>.pub

[core]
	sshCommand = "ssh -i ~/.ssh/<personal_key>"

[core]
	excludesfile = ~/.gitignore 

Notes

  • These steps are macOS specific in some cases, and will also work for Linux system.
  • For windows, the steps are same just commands are different.
  • This are my preferred config settings