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/
@tw-yshuang
Copy link

tw-yshuang commented Dec 14, 2021

I create a CLI command to handle this!
Checkout my repo~~
This repo uses ssh-agent to switch your ssh account.

Git_SSH-Account_Switch

A CLI tool can switch an ssh account to your current shell. You will easily switch to your git account & ssh key when using the server, and using your account to manipulate the project on the server.

Installation

$ bash ./setup.sh

it will add some code in your profile & $logout_profile, and setup git-acc & .gitacc on the $HOME.
file:

git-acc.sh -> $HOME/.git-acc, git-acc function.
.gitacc -> $HOME/.gitacc, save info. that regist on git-acc.

Control

        +---------------+
        |    git-acc    |
        +---------------+

SYNOPSIS

  git-acc [account]|[option]

OPTIONS

  [account]               use which accounts on this shell, type the account name that you register.
  -h, --help              print help information.
  -add, --add_account     build git_account info. & ssh-key.
      -t, --type          ssh-key types, follow `ssh-keygen` rule, 
                          types: dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa(default)
  -rm, --remove_account   remove git_account info. & ssh-key from this device
  -out, --logout          logout your current ssh-acc.


EXAMPLES

  $ git-acc tw-yshuang

@peterblockman
Copy link

@airtonix
Copy link

just use the includeif rule of your gitconfig ... messing with hostnames or cli switcher malarky just leads to complication and non portable setups.

@arcsector
Copy link

For everyone in here who doesn't want to use unique identifiers, just use the Hostname as the Host:

Host github.com
    HostName github.com
    User git
    IdentityFile ...

Now you don't have to remember to change your SSH identifier and you can just copy the "git@github.com..." address from your clone instructions.

@gamesover
Copy link

@arcsector will below work for multiple accounts?

Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_rsa_id1

Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_rsa_id2

@jaanhio
Copy link

jaanhio commented Feb 27, 2022

@gamesover i tried that config too. what happens is, ssh will be able to identify both configuration but only uses the first matching one. so if one of your git command requires id_rsa_id2, the operation will be unsuccessful.

@gamesover
Copy link

gamesover commented Feb 27, 2022

@jaanhio thanks very much for your updates.
True. I found the same issue.
So far, I did not find a perfect solution yet.

Each time, I have to check ssh-add -l to delete unneeded keys and reserve the key needed.

For example, if I need id_rsa_id2, then I will do the below

ssh-add -d ~/.ssh/id_rsa_id1
ssh-add ~/.ssh/id_rsa_id2

To be frank, I guess when initially ssh was designed, they never thought there are a senario that diff acount needs diff keys for the same site.

Previously, github allows the same key was added to diff accounts, so no such issue.
Now, one key can only be used once in the whole github for diff accounts.
So we have such troubles now.

@tomfast
Copy link

tomfast commented Mar 25, 2022

Thanks @jexchan and @mixua. The combination of your answers worked great for me.

@mohlatif227
Copy link

mohlatif227 commented Mar 27, 2022

I'm sharing mine .ssh/config file, hope it helps someone(working fine on MacOS BigSur)

image

Then you have to add your private key ssh agent as below:
ssh-add -K ~/.ssh/work

ssh-add -K ~/.ssh/altif
In final step, you can confirm the connection using below command and get below output if everything setup correctly.

MAltif1M-BNG1:~ Mohammad.Altif$ ssh -T work

Hi <github_username>! You've successfully authenticated, but GitHub does not provide shell access.

MAltif1M-BNG1:~ Mohammad.Altif$ ssh -T altif

Hi <github_username>! You've successfully authenticated, but GitHub does not provide shell access.

@dylb0t
Copy link

dylb0t commented Apr 6, 2022

If your ssh keys don't all show up with
ssh-add -l
you have to run
ssh-add ~/.ssh/yourkey.rsa

7 years later, your reply is still saving lives. My Salute!

+1

@diaojiulishifei
Copy link

From OP's, modified according to @oleweidner @jmpnot you two's, and now it works. Thank y'all!

@maazu
Copy link

maazu commented May 4, 2022

Anyone who is having a problem like in which I followed the instruction on Mac, for some reason when I was attempting to push into the repo from my second account, git was using my first account and I was getting permission denied error, after spending few hours this answer finally helped me https://stackoverflow.com/a/12438179/12702093.

this is how my ~/.ssh/config looks like this

when I am working with my personal account, I use ssh clone like this git@github.com:maazu:repo clone command and when I am using a company account I just clone by git clone repo link

# Company Github Account
Host company.github.com
  HostName github.com
  User github_username
  PreferredAuthentications publickey
  AddKeysToAgent yes
  IdentityFile ~/.ssh/id_ed25519
  IdentitiesOnly yes

# Github.com-personal
Host personal.github.com
  HostName github.com
  User maazu
  AddKeysToAgent yes
  PreferredAuthentications publickey
  IdentityFile ~/.ssh/id_ed25519_personal 
  IdentitiesOnly yes

@HughAJWood
Copy link

You can add this to an existing repo by doing the following:
git config --get remote.origin.url

Which will give you something like:

git@github.com:HughAJWood/repo

Copy and modify the resulting url as so:

git@github.com-<sshId>:HughAJWood/repo
ie
git@github.com-hugh:HughAJWood/repo

This should match the id in the .ssh/config file

# Personal account - the default config
Host github.com-hugh
   HostName github.com
   User git
   IdentityFile ~/.ssh/personal_private_key

@kishore-s-15
Copy link

I had to change the [remote "origin"] / url field in my local .git/config to use the Host defined in .ssh/config in order for this to work, i.e.,

[remote "origin"]
        url = git@github.com-activehacker:activehacker/gfs.git

Without that modification, git would just try to use my default ssh key.

Thanks @oleweidner

Yeah, Even I had to make this change to get it working.

@iamtodor
Copy link

every time I want to interact with a second git account I need to explicitly provide a path to keys: like GIT_SSH_COMMAND="ssh -i ~/.ssh/personal" git push origin master

@danmash
Copy link

danmash commented Aug 13, 2022

I had to remove the wildcard Host * section from the .ssh/config file

@danmash
Copy link

danmash commented Aug 13, 2022

Below are the ~/.gitconfig aliases which could clone with specific github.com replacement and change remote origin URL of existing repo

[alias]
  clc = "!f(){ git clone `sed 's/github.com/github.com-work/g' <<< \"$1\"`;};f"
  Cld = "!f(){ git clone `sed 's/github.com/github.com-default/g' <<< \"$1\"`;};f"
  urlc = "!f(){ git config remote.origin.url `git config remote.origin.url | sed 's/github.com/github.com-work/g'`;};f"
  urld = "!f(){ git config remote.origin.url `git config remote.origin.url | sed 's/github.com/github.com-default/g'`;};f"

use it like git cld github.com/repo to clone repo and replace github.com host to github.com-default automatically

@soumyadeep589
Copy link

I had to change the [remote "origin"] / url field in my local .git/config to use the Host defined in .ssh/config in order for this to work, i.e.,

[remote "origin"]
        url = git@github.com-activehacker:activehacker/gfs.git

Without that modification, git would just try to use my default ssh key.

Thanks!!! working perfectly.

@troccoli
Copy link

troccoli commented Sep 1, 2022

This instructions are great, however for people like me who had a general host configured in .shh/config, you need to make it not generic.

My old .shh/config was:

Host *
  AddKeysToAgent yes
  IdentityFile ~/.ssh/id_ed25519

Following the instructions above I ended up with:

Host github.troccoli
  HostName github.com
  User git
  IdentityFile ~/.ssh/troccoli
Host *
  AddKeysToAgent yes
  IdentityFile ~/.ssh/id_ed25519

But when pushing to my personal repository I had the following error:

ERROR: Permission to troccoli/tubecrush.git denied to CLL-GTA.
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

Where CLL-GTA is my work git account.

The solution was to make the general host not general any more:

Host github.troccoli
  HostName github.com
  User git
  IdentityFile ~/.ssh/troccoli
Host work
  HostName github.com:****
  AddKeysToAgent yes
  IdentityFile ~/.ssh/id_ed25519

The **** is actually my company account on GitHub. To find it, I just looked in the .git/config file in any of the repositories I cloned for work.

I hope this helps.

@Ronghaozhang
Copy link

Ronghaozhang commented Sep 3, 2022

According to ssh documentation, we need set a appropriate value for User in the config file.
git clone git@github.com:githubAccountName/repoName.git

config file:

Host github.com
   HostName github.com
   IdentityFile ~/.ssh/id_rsa_personal
   User githubAccountName

@keikoro
Copy link

keikoro commented Sep 9, 2022

@Ronghaozhang This is incorrect. The User in the ssh config file is the user with which you connect to/log into the remote server, which is git by default. Compare with the Git URLs provided by platforms like GitHub, GitLab etc. for SSH access, e.g. git@github.com:github/docs.git. The part before the colon translates to user@hostname. See the man page for ssh for more details.

If you had tried out your suggestion before posting it, you would have known it doesn't work – GitHub will return a permission error if you try to connect with a user other than git.

Btw. the link you included needs to be reformatted. It doesn't point to where you wanted it to go, but only displays the address.

@matt2930
Copy link

An update to this after spending too long on it. My scenario was that I had originally set up my ssh config like so:

Host github.com
  IdentityFile ~/.ssh/github
  IdentitiesOnly yes
  AddKeysToAgent yes

I had cloned tons of repos using this config, so I could not use the option of setting different hosts, because there were too many repos to update. What I needed to do was be able to push/pull for one repo using a different identity file, so I tried doing this in that one repo:
git config core.sshCommand "ssh -i ~/.ssh/matt2930-github -o 'IdentitiesOnly=yes'"

But what happened was no matter what, it was still using the identity file I had defined in my ~/.ssh/config. What saved me was adding -F /dev/null to my ssh command:
git config core.sshCommand "ssh -i ~/.ssh/matt2930-github -o 'IdentitiesOnly=yes' -F /dev/null"

From man ssh:

 -F configfile
         Specifies an alternative per-user configuration file.  If a configuration file is given on the command line, the system-wide configuration file (/etc/ssh/ssh_config) will be ignored.  The default for the
         per-user configuration file is ~/.ssh/config.  If set to “none”, no configuration files will be read.

@Ronghaozhang
Copy link

Ronghaozhang commented Sep 20, 2022

@Ronghaozhang This is incorrect. The User in the ssh config file is the user with which you connect to/log into the remote server, which is git by default. Compare with the Git URLs provided by platforms like GitHub, GitLab etc. for SSH access, e.g. git@github.com:github/docs.git. The part before the colon translates to user@hostname. See the man page for ssh for more details.

If you had tried out your suggestion before posting it, you would have known it doesn't work – GitHub will return a permission error if you try to connect with a user other than git.

Btw. the link you included needs to be reformatted. It doesn't point to where you wanted it to go, but only displays the address.

Thanks for pointing out the link issue. Before saying it's doesn't work, I'm not sure you have tried my method, it's working perfectly on my laptop, for both my personal account and working account.

Also, this is the screenshot from Github documentation, it pointed out the part after the colon is the user.
image

Here the link: https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories

@keikoro
Copy link

keikoro commented Sep 22, 2022

@Ronghaozhang The user on GitHub, which identifies a repository owner, has nothing to do with the user used for SSH, which is what you set when you provide a value for User in the ssh config. Again, see the man page for ssh to learn how ssh works.

GitHub even describes how to test your connection in their docs:
Testing your SSH connection
Error: Permission denied (publickey)

You will not not get a permission error when you provide an SSH user that is not git and test your connection as described.

The reason you think "it works" – by which I assume you mean fetching, pulling, pushing etc. – is likely that you continue to use the correct user git@ in your remote URLs, which overrides the User variable in the config file.

@Zeeshnhmd
Copy link

Nice, I am done with the above configuration.

Now, how to push my new project code to my personal account if I am using two GitHub accounts?

@GeoSot
Copy link

GeoSot commented Oct 5, 2022

This seems straight-lined too 8 Easy Steps to Set Up Multiple GitHub Accounts

@lukezhang-123
Copy link

lukezhang-123 commented Oct 22, 2022

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

@reservedmuffin
Copy link

reservedmuffin commented Oct 28, 2022

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
  1. Do the same for your project B with ~/.ssh/id_second_key

@emptyminds2020
Copy link

I'm sharing mine .ssh/config file, hope it helps someone(working fine on MacOS BigSur)

image

Then you have to add your private key ssh agent as below: ssh-add -K ~/.ssh/work

ssh-add -K ~/.ssh/altif In final step, you can confirm the connection using below command and get below output if everything setup correctly.

MAltif1M-BNG1:~ Mohammad.Altif$ ssh -T work

Hi <github_username>! You've successfully authenticated, but GitHub does not provide shell access.

MAltif1M-BNG1:~ Mohammad.Altif$ ssh -T altif

Hi <github_username>! You've successfully authenticated, but GitHub does not provide shell access.

+1, Thanks for sharing this.

@DH-Intive
Copy link

If after applying this gist one is still experiencing the problem in Android Studio, try unchecking "use credential helper" parameter in Settings -> Version Control -> Git. That helped me.

@ToyVo
Copy link

ToyVo commented Jan 20, 2023

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.<base>.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

@JakeVaults
Copy link

I had to remove the wildcard Host * section from the .ssh/config file

Hot tip

@dbolser
Copy link

dbolser commented Jan 23, 2023

I had to remove the wildcard Host * section from the .ssh/config file

You shouldn't have to remove it. Add it to the end (assuming there is anything you want to apply to all hosts). The order of precedence in that config file always confuses me.

Mine looks like this:

## GIT
Host placeholder.github.com github
User git
LogLevel INFO
Hostname github.com
IdentitiesOnly yes
IdentityFile ~/.ssh/placeholder.id_ed25519
...
## Applied to all...
Host *
ServerAliveInterval 240
ServerAliveCountMax 2
ForwardX11 no

@adminka-root
Copy link

@yinzara
Copy link

yinzara commented Feb 1, 2023

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

@abhisri1997
Copy link

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

@msaysabio
Copy link

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

Hey I followed this instruction but I still get ssh: Could not resolve hostname github.com-work: nodename nor servname provided, or not known
fatal: Could not read from remote repository.

I already added my public key to github too

@SketchyDeveloper
Copy link

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

Hey I followed this instruction but I still get ssh: Could not resolve hostname github.com-work: nodename nor servname provided, or not known fatal: Could not read from remote repository.

I already added my public key to github too

Your repo name should be changed from
git@github.com:abhisri1997/mailer.git
this to
this - gh_personal:abhisri1997/mailer.git

From the error you get I can still see github.com-work:

Change this to your ssh host

@airtonix
Copy link

airtonix commented Apr 13, 2023

munging your .git/config remote is just going to end up being a hassle in the long run.

trust me, been there done that, never doing it again tomorrow.

the. most. portable. way is to setup your root gitconfig so that it uses the includeif.

edit: like mentioned here:
https://gist.github.com/jexchan/2351996?permalink_comment_id=4456452#gistcomment-4456452


The includeif stanza/directive modifies your git config on the fly based on the CWD of the git operation.
Relevant to this thread, this is where we can teach git about the ssh_command, which is where you point to your shiny unique ssh key.

The end result is a set of dotfiles ~/.gitconfig, ~/.dotfiles/this.gitconfig, ~/.dotfiles/that.gitconfig you can carry around and a directory structure for your ~/Projects

~/.gitconfig

[core]
	editor = DISPLAY=:1 code --wait

[init]
	defaultBranch = master

[rerere]
	enabled = true

[includeIf "gitdir:Projects/Mine/Gitlab/"]
        path = ~/.dotfiles/mine-gitlab.gitconfig

[includeIf "gitdir:Projects/Mine/Github/"]
        path = ~/.dotfiles/mine-github.gitconfig

[includeIf "gitdir:Projects/Experiements/Github/"]
        path = ~/.dotfiles/mine-github.gitconfig

[includeIf "gitdir:Projects/Work/Github/SomeCompany"]
        path = ~/.dotfiles/work-somecompany.gitconfig

Personal Configs

~/.dotfiles/mine-gitlab.gitconfig

[user]
name = My Name
email = other.e@ma.il

~/.dotfiles/mine-github.gitconfig

[user]
name = My Name
email = mygithubusername@users.noreply.github'com
signingkey = DEADBEEF

[commit]
gpgsign = true

[gpg]
program = age

For the above, any git operations occurring within a path that matches either:

  • Projects/Mine/Gitlab/
  • Projects/Mine/GitHub/, or
  • Projects/Experiements/Github/

will use my github config.

Work Configs

~/.dotfiles/work-github-somecompany.gitconfig

[core]
sshCommand = "ssh -o IdentitiesOnly -i ~/.ssh/id_rsa-mymachinename-github-somecompany -F /dev/null"

For the above, any git operation occuring in a directory that matches Projects/Work/Github/SomeCompany will specifically use a different ssh key despite my ~/.ssh/config declaring another for other general github ssh connections. The -o IdentitiesOnly tells ssh to use only the private key specified with the "-i" option and ignore any other keys in the SSH agent or on the remote server.


The main reasons I love this setup :

can just copy paste a github git repo url with wild abandon and paste it without having to remember the magical things to modify.

don't have to do anything in the ~/.ssh/config since what we really wanted this for was git and nothing else.

@vaynevayne
Copy link

You can use this https://github.com/adminka-root/git_switcher

Boss, can you develop a GUI software if you are free? It's like switchHost. It's convenient.

@adminka-root
Copy link

Boss, can you develop a GUI software if you are free? It's like switchHost. It's convenient.

I needed to switch between accounts as part of a training session for children to show how development works in a team. I wrote a quick solution that I don't use in my daily life. I agree that it would be nicer with a GUI and a tray icon. But I'm busy enough to do it. I can recommend Glade and Vala or PyGTK, which will allow you to quickly create a modern interface on gtk. You could develop the interface yourself, and my source code would probably speed up the process.

@tranthaihoang
Copy link

tranthaihoang commented Jun 2, 2023

On Macbook, it works

Host github.com
HostName github.com
User your_user_account_github
PreferredAuthentications publickey
IdentityFile ~/.ssh/your_user_account_github_rsa
IdentitiesOnly yes

@pabloripoll
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
  1. Do the same for your project B with ~/.ssh/id_second_key

This was the best solution for me! Thanks!

@mbean-epc
Copy link

Formerly, I enjoyed the simplicity of SSH config way of doing this. I have changed my mind because I ran into a project with submodules. Projects like this have hard-coded committed references to URLs. I cannot simply use personal.github.com vs work.github.com with such projects without modifying the .gitmodules. I even tried that and git seems to have become confused.

Therefore the IncludeIf approach might actually be most compatible with the most projects. Although it is not exactly Windows friendly. Definitely Linux-friendly!

@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

@rio-ap
Copy link

rio-ap commented Jul 11, 2024

munging your .git/config remote is just going to end up being a hassle in the long run.

trust me, been there done that, never doing it again tomorrow.

the. most. portable. way is to setup your root gitconfig so that it uses the includeif.

edit: like mentioned here:
https://gist.github.com/jexchan/2351996?permalink_comment_id=4456452#gistcomment-4456452

The includeif stanza/directive modifies your git config on the fly based on the CWD of the git operation. Relevant to this thread, this is where we can teach git about the ssh_command, which is where you point to your shiny unique ssh key.

The end result is a set of dotfiles ~/.gitconfig, ~/.dotfiles/this.gitconfig, ~/.dotfiles/that.gitconfig you can carry around and a directory structure for your ~/Projects

~/.gitconfig

[core]
	editor = DISPLAY=:1 code --wait

[init]
	defaultBranch = master

[rerere]
	enabled = true

[includeIf "gitdir:Projects/Mine/Gitlab/"]
        path = ~/.dotfiles/mine-gitlab.gitconfig

[includeIf "gitdir:Projects/Mine/Github/"]
        path = ~/.dotfiles/mine-github.gitconfig

[includeIf "gitdir:Projects/Experiements/Github/"]
        path = ~/.dotfiles/mine-github.gitconfig

[includeIf "gitdir:Projects/Work/Github/SomeCompany"]
        path = ~/.dotfiles/work-somecompany.gitconfig

Personal Configs

~/.dotfiles/mine-gitlab.gitconfig

[user]
name = My Name
email = other.e@ma.il

~/.dotfiles/mine-github.gitconfig

[user]
name = My Name
email = mygithubusername@users.noreply.github'com
signingkey = DEADBEEF

[commit]
gpgsign = true

[gpg]
program = age

For the above, any git operations occurring within a path that matches either:

  • Projects/Mine/Gitlab/
  • Projects/Mine/GitHub/, or
  • Projects/Experiements/Github/

will use my github config.

Work Configs

~/.dotfiles/work-github-somecompany.gitconfig

[core]
sshCommand = "ssh -o IdentitiesOnly -i ~/.ssh/id_rsa-mymachinename-github-somecompany -F /dev/null"

For the above, any git operation occuring in a directory that matches Projects/Work/Github/SomeCompany will specifically use a different ssh key despite my ~/.ssh/config declaring another for other general github ssh connections. The -o IdentitiesOnly tells ssh to use only the private key specified with the "-i" option and ignore any other keys in the SSH agent or on the remote server.

The main reasons I love this setup :

can just copy paste a github git repo url with wild abandon and paste it without having to remember the magical things to modify.

don't have to do anything in the ~/.ssh/config since what we really wanted this for was git and nothing else.

thank you, this work best for my need

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