Skip to content

Instantly share code, notes, and snippets.

@jexchan
Created April 10, 2012 15:00
Show Gist options
  • Save jexchan/2351996 to your computer and use it in GitHub Desktop.
Save jexchan/2351996 to your computer and use it in GitHub Desktop.
Multiple SSH keys for different github accounts

Multiple SSH Keys settings for different github account

create different public key

create different ssh key according the article Mac Set-Up Git

$ ssh-keygen -t rsa -C "your_email@youremail.com"

Please refer to github ssh issues for common problems.

for example, 2 keys created at:

~/.ssh/id_rsa_activehacker
~/.ssh/id_rsa_jexchan

then, add these two keys as following

$ ssh-add ~/.ssh/id_rsa_activehacker
$ ssh-add ~/.ssh/id_rsa_jexchan

you can delete all cached keys before

$ ssh-add -D

finally, you can check your saved keys

$ ssh-add -l

Modify the ssh config

$ cd ~/.ssh/
$ touch config
$ subl -a config

Then added

#activehacker account
Host github.com-activehacker
	HostName github.com
	User git
	IdentityFile ~/.ssh/id_rsa_activehacker

#jexchan account
Host github.com-jexchan
	HostName github.com
	User git
	IdentityFile ~/.ssh/id_rsa_jexchan

Clone you repo and modify your Git config

clone your repo git clone git@github.com:activehacker/gfs.git gfs_jexchan

cd gfs_jexchan and modify git config

$ git config user.name "jexchan"
$ git config user.email "jexchan@gmail.com" 

$ git config user.name "activehacker"
$ git config user.email "jexlab@gmail.com" 

or you can have global git config $ git config --global user.name "jexchan" $ git config --global user.email "jexchan@gmail.com"

then use normal flow to push your code

$ git add .
$ git commit -m "your comments"
$ git push

Another related article in Chinese

  1. http://4simple.github.com/docs/multipleSSHkeys/
@keikoro
Copy link

keikoro commented Jul 11, 2023

@mbean-epc Could you elaborate?

I use two SSH keys in parallel for a project with submodules without problem. The location of the repo(s) provided in .gitmodules has nothing to do with how you access them while working with them. The only thing you may have run into that I can think of is that your git config may need minor manual adaptation after initialising the project.

@mbean-epc
Copy link

@keikoro Did you set your configurations before you clone the repository that had submodules? I think I tried both before and after. One seemed to work. The other did not. This is what I mean by "git seems to have become confused".

If you cannot replicate using those steps, please do let me know. I should definitely retry if it is working for you.

My setup: the projects in.gitmodules are also work projects. Ideally I would just update each and then be back to coding again.

@keikoro
Copy link

keikoro commented Jul 12, 2023

@mbean-epc Your system doesn't know which SSH key you want it to use for a specific project, so it'll default to whatever it thinks is your default key, unless the remote URLs for your repos contain an alias it can match to a different config.

So, if you initially clone a repo without providing the alternative host name you use in your SSH config, you'll have to manually change the remote URL after. The same is true for any submodules – which are regular repos, except their config is saved in the .git folder of the superproject which contains them.

If you can initialise the project fine, i.e. there's no issue with permissions which would prevent you from cloning/fetching with your default user, you'll have to then go through all config files in the uppermost .git directory and adapt the remote URLs to fetch from/push to. The config for the superproject is in the usual path, .git/config, the config files for the submodules are in .git/modules/SUBMODULE_NAME/config, where SUBMODULE_NAME matches the section header in the .gitmodules file, e.g.

[submodule "SUBMODULE_NAME"]
	path = ...
	url = ...
	branch = ...
	...

In your config files, you'll have to find your remote and adapt its url value from the default...

[remote "my_remote"]
	url = git@github.com:my_org/my_repo.git

... to whatever you use in your SSH config:

[remote "my_remote"]
	url = git@my-ssh-alias:my_org/my_repo.git

@mbean-epc
Copy link

@keikoro thank you for providing that. Again, that he gets to the point where things are just a bit too messy for me and unintuitive for a given repo. So at that point the IncludeIf seems like the approach I would tell everyone else to use if they are just now starting out.

@raffienficiaud
Copy link

@mbean-epc the easiest is just to start another ssh-agent, pull the ssh key of that repo into that agent, and do all the git operations in the same terminal of that agent. This is dead simple, does not require setting any ssh-config or touch any configuration of the repository you are trying to pull. See this for details.

@cr0wg4n
Copy link

cr0wg4n commented Jul 14, 2023

Or use this script instead https://gist.github.com/cr0wg4n/39e691d5f2140bce641448b0f56e6a9e πŸ˜„

switch-github-user.sh

#!/bin/bash
gh_user="${1:-Nothing}"

if [ "$gh_user" == 'USERNAME_1' ]; then
  ssh-add -D
  git config --global user.email "USERNAME_1_EMAIL"
  ssh-add /PRIVATE_KEY_PATH/.ssh/github-USERNAME_1
elif [ "$gh_user" == 'USERNAME_2' ]; then
  ssh-add -D
  git config --global user.email "USERNAME_2_EMAIL"
  ssh-add /PRIVATE_KEY_PATH/.ssh/github-USERNAME_2
else
  echo 'Nothing was applied'
  exit 1
fi
echo "$gh_user applied!"
git config user.email
ssh -T git@github.com
exit 0

# TO USE 
# ./switch-github-user.sh USERNAME_1

@mbean-epc
Copy link

Minimal, single place. Assumes only 2 profiles, but that is often the case. I like it @cr0wg4n!

@cr0wg4n
Copy link

cr0wg4n commented Jul 14, 2023

Minimal, single place. Assumes only 2 profiles, but that is often the case. I like it @cr0wg4n!

Thanks @mbean-epc! We can refactor :D as need, but it is a simple answer to a simple problem hahaha :D

@zjhken
Copy link

zjhken commented Jul 17, 2023

change the default host from "github.com" to "github.com-activehacker", then the ssh will recognize your ssh key which defined in ssh config.

ssh -T git@github.com-activehacker
git clone <Host in ssh config>:<github username>/<github repo name>.git
git clone github.com-activehacker:activehacker/mygit.git
git clone github.com-jexchan:jexchan/mygit.git

the only correct answer

@mbean-epc
Copy link

@zjhken That work. I've effectively been using an automated form of that for a long time. It is great for terminals that preserve history that have engineers who know how to do reverse lookup. Bonus if the engineers are familiar with the auth error they would get if they forget.

@roeniss
Copy link

roeniss commented Jul 31, 2023

ssh -T git@github.com-activehacker
git clone :/.git
git clone github.com-activehacker:activehacker/mygit.git
git clone github.com-jexchan:jexchan/mygit.git

In my case, git@ was essential.

git clone git@github.com-activehacker:activehacker/mygit.git
git clone git@github.com-jexchan:jexchan/mygit.git

@habsfanongit
Copy link

I use this https://github.com/sageil/ghswitch on both mac and linux. I found it easier since I used email addresses as my comments when I created the ssh keys for my personal and professional accounts

@Vadorequest
Copy link

Thank you a lot for this, I've struggled a long time to get this right.

I've mentioned your article in this SO question/answer:
https://stackoverflow.com/a/76952155/2391795

@ll01
Copy link

ll01 commented Oct 7, 2023

are you able to edit the GitHub UI so when you click the copy to clipboard you will get the different host? e.g. github.com-jexchan I'm scared I'm going to forget this change and be confused why the repo isn't cloning

@jananpatel2002
Copy link

sshCommand

Good catch! Defining the sshCommand is not described in most of the guides I've seen.
In case you have for instance two separate Github accounts and two separate projects (project A and project B) you'd like to have two separate ssh-keys for:

1. Open an A project's `.git/config` file

2. Add
  [core]
     ...
    sshCommand = ssh -i ~/.ssh/id_first_key
3. Do the same for your project B with `~/.ssh/id_second_key`

If only git had a url..sshCommand like https://git-scm.com/docs/git-config#Documentation/git-config.txt-urlltbasegtinsteadOf then this whole problem could be simple in the global git config

[url "ssh://git@github.com/org1"]
  sshCommand = ssh -i ~/.ssh/id_org1
[url "ssh://git@github.com/org2"]
  sshCommand = ssh -i ~/.ssh/id_org2

come to think of it url fields for name, email, and signingkey would eliminate a lot of manual overriding

You savior. This actually fixed all my issues LOL

@demjm
Copy link

demjm commented Oct 29, 2023

After digging for a while here's the issue I found and the fix:

This is the config file for ssh located @ ~/.ssh/config

#BitBucket Account
Host bb_work
	HostName bitbucket.org
	User git
	IdentityFile ~/.ssh/bb_work

#Personal account
Host gh_personal
	HostName github.com
	User git
	IdentityFile ~/.ssh/gh_personal

And this is the config file for the remote repo:

[remote "origin"]
      url = gh_personal:abhisri1997/mailer.git
      fetch = +refs/heads/*:refs/remotes/origin/*

You can notice that I have changed my remote repo URL from: git@github.com:abhisri1997/mailer.git to gh_personal:abhisri1997/mailer.git

How this works:

You'd like to establish an ssh connection to the GitHub server to read/write the data to your repo for that you have created the key by reading the above article.

Now whenever you do a git pull/push or whenever you want to establish a connection to GitHub using the git command

It will check your ssh config file to check if the host is defined with git@github.com but it will find nothing.

So it won't be able to shake the earlier created private and public keys.

So in order to do that we have to change our repo URL("git@github.com:abhisri1997/mailer.git ") to the HOST value (gh_personal) set in ~/.ssh/config

works πŸ‘Œ

@GerretS
Copy link

GerretS commented Dec 1, 2023

I just spent an hour trying to follow the instructions in this gist and nothing worked, it kept trying to use the wrong host/key.

Turns out that at some point I had deleted my public key from my Github account.

Apparently ssh/git then automatically falls back to your other ssh key and doesn't tell you at all.

So uh... if nothing else works check your Github SSH settings. πŸ˜“

@shivanshPurple
Copy link

shivanshPurple commented Dec 28, 2023

@abhisri1997 solution works for me too. Was stuck on this for too much time. +1

@fhayes301
Copy link

Thank you! This worked for me.

@rnag
Copy link

rnag commented Jan 27, 2024

I've also written a pretty good Gist about another approach: https://gist.github.com/yinzara/bbedc35798df0495a4fdd27857bca2c1

Excellent write-ups! This and the linked article are both great to read through. I am new to SSH and GPG in GitHub so I needed to spend a lot of time to get up to speed.

FYI I recently got a new personal Macbook, so I found I've needed this sort of setup for git since I use one account for work, and another for personal stuff.

In case it's useful to others, I've gathered all the useful steps in the main steps, into a Bash/shell script. Helps for automation purposes, so e.g. less manual work, and also less things to remember.

Please do check it out and let me know (link below). I welcome any PRs or updates to script if needed. I tested this extensively on a Mac environment.

https://github.com/rnag/Mac-Quickstart/blob/main/scripts/bootstrap_ssh_for_github.sh


Updates:

  • I liked @airtonix suggestion on creating a ~/.dotfiles folder and adding all project .gitconfig there, so I've updated the script to do that.
  • I just got around to updating the script to handle semi-automated GPG key setup, for Git commit verification! Check it out. This simplifies the process a whole lot so you don't have to think about it, just copy paste some stuff around!

After running the script, file/directory structure in user home ~ would now look as follows:

.gitignore
Git-Projects/
β”œβ”€β”€ Personal
└── Work
.dotfiles
β”œβ”€β”€ Personal-github.gitconfig
└── Work-github.gitconfig
.ssh
β”œβ”€β”€ config
β”œβ”€β”€ id_ed25519_<gh_user>
β”œβ”€β”€ id_ed25519_<gh_user>.pub
β”œβ”€β”€ known_hosts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment