I tried to clone several repositories in two different GitHub accounts and I found even such simple task took me several hours and the main issue was that the ssh-agent always provided the cached keys one by one.
Mostly such behaviour was not a big issue as different users/hosts will be mapped to different keys and ssh-agent will find the right key after several attempts, while for GitHub accounts the story is a little complex as in fact the same user (git) and same host (github.com) are used for logging. So every key is valid while their permissions are different and I found every time the first cached key would be used to access github.com and of course it would fail to access some repos.
One possible solution is using option 'IdentitiesOnly yes' in the ssh config file while it will force you to input the password every time so the ssh-agent becomes useless.
Some guys have mentioned the right way to allow the ssh-agent to select the right key for the corresponding account, while the instructions are not so clear so I collected all the need information and wrote them here.
I use Git on Windows 10 and I believe some configurations could be used on other platforms also.
I have two GitHub accounts, one for personal usage and another one for my friend.
When I created the private keys for them, I gave informatory comments to them and the comments were later used in the ssh config file also. For personal key, the comment was 'dbcloudsvc' and another one was 'latipay'. Here any file names could be used and only the comments should be chosen for better usage. All the private keys have '.key' as suffix and the corresponding public keys have '.pub' suffixes for easy management.
I created a .bashrc file in the user home directory to load all the private keys when I started the Git Bash program. All the private keys have the '.key' suffixes so I need not to update this file to include new created keys.
env=~/.ssh/agent.env agent_load_env () { test -f "$env" && . "$env" >| /dev/null ; } agent_start () { (umask 077; ssh-agent >| "$env") . "$env" >| /dev/null ; } agent_load_env # agent_run_state: 0=agent running w/ key; 1=agent w/o key; 2=agent not running agent_run_state=$(ssh-add -l >| /dev/null 2>&1; echo $?) if [ ! "$SSH_AUTH_SOCK" ] || [ $agent_run_state = 2 ]; then agent_start ssh-add ~/.ssh/*.key elif [ "$SSH_AUTH_SOCK" ] && [ $agent_run_state = 1 ]; then ssh-add ~/.ssh/*.key fi unset env
And the ssh config file:
#Personal Account Host dbcloudsvc HostName github.com PreferredAuthentications publickey User git ForwardAgent yes IdentityFile ~/.ssh/NeilZhang.pub # Friend GitHub account Host latipay HostName github.com PreferredAuthentications publickey User git ForwardAgent yes IdentityFile ~/.ssh/NeilZhang-LatiPay.pub
The trick here is to use the public files and not the private keys, and you could create them using below commands in the Git Bash.
neilzh@BBDSXL-E485 MINGW64 ~ $ ssh-add -l 2048 SHA256:8QZdCoB7W18kCaVn1D4slKuw726q4c2vyUn5Q/c/b38 dbcloudsvc (RSA) 4096 SHA256:+9riIM3mrQyYCcBBVC1WtxJ7H3tnuN0+pycuGT6wIrM latipay (RSA) neilzh@BBDSXL-E485 MINGW64 ~ $ ssh-add -L|grep 'dbcloudsvc' > ~/.ssh/NeilZhang.pub neilzh@BBDSXL-E485 MINGW64 ~ $ ssh-add -L|grep 'latipay' > ~/.ssh/NeilZhang-LatiPay.pub
Then you could verify the right keys were used for different accounts in different repos.
neilzh@BBDSXL-E485 MINGW64 ~ $ cd f: neilzh@BBDSXL-E485 MINGW64 /f $ cd GitHub/DBCloudSVC/ neilzh@BBDSXL-E485 MINGW64 /f/GitHub/DBCloudSVC (master) $ ssh -T git@dbcloudsvc Hi bbdsxl! You've successfully authenticated, but GitHub does not provide shell access. neilzh@BBDSXL-E485 MINGW64 /f/GitHub/DBCloudSVC (master) $ cd ../LatiPay/parasite-python/ neilzh@BBDSXL-E485 MINGW64 /f/GitHub/LatiPay/parasite-python (master) $ ssh -T git@latipay Hi xxxxxx2! You've successfully authenticated, but GitHub does not provide shell access.