How to setup SSH and git to handle multiple accounts
This page describes how to handle multiple git accounts using SSH on Windows. Note that mail accounts etc in the below codesnippets are not the real ones, but the process has been tested and works.
In most cases HTTPS is the easiest way to work with e.g., GitHub. However, if you have more than one account, HTTPS becomes a mess and may not work at all. You may have multiple accounts if you are e.g. working with your companys GitHub, but also contributing to an Open Source project using a private mail-address. Another example could be working on GitHub and GitLab.
The examples are created using Git Bash (the one installed with git on a windows PC). Some commands are the same in Power Shell, while others have 1:1 pendants.
The overall concepts
These are the basic steps:
One time operations:
- Create a public/private key-pair per account. This can be RSA or - more likely - ed25519 based.
- At the homepage for each account you register your public key. This is the one with extension 'pub'.
- Setup git to understand which key relates to which repo - so that you can write e.g., 'git push' and the right source goes to the right repo.
More frequent operations (can be scripted):
- Assure that an ssh-agent is running - if not start it.
- Add the private key needed for the work you need to do (or all private keys to make life simpler) to the agent.
- The agent and e.g., GitHub now have what they need to do their secret handshake.
Now follows an example where I work on a private project as well as on company projects on the same PC.
Generate key-pair - for each user-account.
The first key-pair I call personal to avoid mixing with private used in keys.Thus id_ed25519_personal_github is my private personal account key and id_ed25519_personal_github.pub is my public personal account key. Note that you don't see my keys anywhere here - only 'fingerprints' and hashes. I run all the code in git bash.
$ ssh-keygen -t ed25519 -C "kelk@mail.com" -f ~/.ssh/id_ed25519_personal_github
Generating public/private ed25519 key pair.
Enter passphrase for "/c/Users/kelk/.ssh/id_ed25519_personal_github" (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /c/Users/kelk/.ssh/id_ed25519_personal_github
Your public key has been saved in /c/Users/kelk/.ssh/id_ed25519_personal_github.pub
The key fingerprint is:
SHA256:nBsIGF5p+ZnIrNIkwZWNjRU4XHbdlCoBaJRv/WKeJeY kelk@mail.com
The key's randomart image is:
+--[ED25519 256]--+
| oo+*=+ oo.. |
| *O.=.o o |
| o=o=... . |
|. . o+ = o |
|.. o.o.o= |
| . + += = |
|.. . = * |
|..o E |
| .o. |
+----[SHA256]-----+
Add PRIVATE key to SSH Agent
The private key is in the file that does not have the "pub" extension.
$ ssh-add ~/.ssh/id_ed25519_personal_github
Identity added: /c/Users/kelk/.ssh/id_ed25519_personal_github (kelk@mail.com)
ADD SSH (pub) key in GitHub - for relevant repos (just root)
Go to github.com, login, click on your profile image (top right corner) and go to settings. Find 'SSH and GPG keys'. Click, and then press green button 'New SSH key'. When asked, hand over the file with the "pub" extension.
Repeat all the above for the other account
I call it "work" in the sample code.
Create the switch-field for SSH and git
Create a new file for the switch-field for the repos and keys - here "C:\Users\kelk.ssh\config". Put in the details for the two accounts.Note that the 'Host github.com-personal' refers to github.com, while 'personal' is just a name I invented. This name is reused when setting up git in the next step.
# Personal GitHub account
Host github.com-personal
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_personal_github.pub
# Work GitHub account
Host github.com-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519.pub
Tell the repo which SSH-key and host it belongs to
In the repo for the personal work:
$ git remote set-url origin git@github.com-personal:personal_user/personal_repo.git
In the repo for the work work:
$ git remote set-url origin git@github.com-work:work_user/work_repo.git
Testing
Now test:
$ git push
Enumerating objects: 86, done.
Counting objects: 100% (86/86), done.
Delta compression using up to 8 threads
Compressing objects: 100% (73/73), done.
Writing objects: 100% (76/76), 4.68 MiB | 4.18 MiB/s, done.
Total 76 (delta 15), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Resolving deltas: 100% (15/15), completed with 4 local objects.
To github.com-personal:personal_user/personal_repo.git
cdfb3fc..394f75f master -> master
Make it reusable
I quickly learned that the agent closes down at various occasions. Thus, the keys and config are persisted in ~/.ssh, and the git config also stays, but the agent needs to get on the road again.
IF the authentication agent is not running, this is how you start it:
eval "$(ssh-agent -s)"
You can (off course) check the state and content of the agent with
ssh-add -l
In my case I needed to rerun (e.g. in startup-file):
ssh-add ~/.ssh/id_ed25519_personal_github
ssh-add ~/.ssh/id_ed25519
Testing again:
$ ssh-add -l
256 SHA256:nBsIGF5p+ZnIrNIkwZWNjRU4XHbdlCoBaJRv/WKeJeY kelk@mail.com (ED25519)
256 SHA256:8T2DQzgPy5QOsT35CwCRjiowqHa8ksfR+A9Or1KMO6M kelk@work.com (ED25519)
Setting it all up in .bash_profile
I have added the following code in .bash_profile - if you use Power Shell it is NOT the same:
#Is the SSH agent running? Presence of the file is NOT enough
env_file=~/.ssh/agent.env
agent_is_running() {
[ -f "$env_file" ] || return 1
source "$env_file" > /dev/null
[ -S "$SSH_AUTH_SOCK" ] && ps -p "$SSH_AGENT_PID" > /dev/null 2>&1
}
if ! agent_is_running; then
echo "Starting new ssh-agent..."
eval "$(ssh-agent -s | grep -v '^echo ')" > "$env_file"
source "$env_file" > /dev/null
fi
#Add keys if none are loaded (risking that one is and the other isn't
ssh-add -l > /dev/null || ssh-add ~/.ssh/id_ed25519 ~/.ssh/id_ed25519_personal_github
#Note that this can start multiple instances of ssh-agent - not really a problem
hint: In these scripts returning 1 is false and 0 is true 😃
Moving to another PC
I guess not everyone considers it safe to copy the keys - with the config - from one PC to another, by copying the contents of the ~/. ssh folder. But the fact that it works, proves that there is no other steps involved. The above defines all steps and all participants.Should you decide to copy a given setup, then don't forget the .bash_profile. The alternative is to make new keypairs, register the public ones at e.g., github and feed the new private ones to the ssh-agent.