Skip to content

Instantly share code, notes, and snippets.

@oanhnn
Last active November 21, 2024 05:17
Show Gist options
  • Save oanhnn/80a89405ab9023894df7 to your computer and use it in GitHub Desktop.
Save oanhnn/80a89405ab9023894df7 to your computer and use it in GitHub Desktop.
Using multiple github accounts with ssh keys

Problem

I have two Github accounts: oanhnn (personal) and superman (for work). I want to use both accounts on same computer (without typing password everytime, when doing git push or pull).

Solution

Use ssh keys and define host aliases in ssh config file (each alias for an account).

How to?

  1. Generate ssh key pairs for accounts and add them to GitHub accounts.

  2. Edit/Create ssh config file (~/.ssh/config):

    # Default github account: oanhnn
    Host github.com
       HostName github.com
       IdentityFile ~/.ssh/oanhnn_private_key
       IdentitiesOnly yes
       
    # Other github account: superman
    Host github-superman
       HostName github.com
       IdentityFile ~/.ssh/superman_private_key
       IdentitiesOnly yes
    

    NOTE: If you use any account frequently, you should use the default hostname (github.com).

  3. Add ssh private keys to your agent:

    $ ssh-add ~/.ssh/oanhnn_private_key
    $ ssh-add ~/.ssh/superman_private_key
  4. Test your connection

    $ ssh-keyscan github.com >> ~/.ssh/known_hosts
    $ ssh -T [email protected]
    $ ssh -T git@github-superman

    If everything is OK, you will see these messages:

    Hi oanhnn! You've successfully authenticated, but GitHub does not provide shell access.
    Hi superman! You've successfully authenticated, but GitHub does not provide shell access.
  5. Now all are set, you need remeber

    git@github-superman:org/project.git => user is superman
    [email protected]:org/project.git.     => user is oanhnn
    
  • If you need clone a repository, just do:
$ git clone git@github-superman:org1/project1.git /path/to/project1
$ cd /path/to/project1
$ git config user.email "[email protected]"
$ git config user.name  "Super Man"
  • If you already have the repo set up, after the ssh config instructions, you need change the URL of origin, just do:
$ cd /path/to/project2
$ git remote set-url origin git@github-superman:org2/project2.git
$ git config user.email "[email protected]"
$ git config user.name  "Super Man"
  • If you are creating a new repository on local:
$ cd /path/to/project3
$ git init
$ git remote add origin git@github-superman:org3/project3.git
$ git config user.email "[email protected]"
$ git config user.name  "Super Man"
$ git add .
$ git commit -m "Initial commit"
$ git push -u origin master

Done! Goodluck!

Addon:

The bash script that prompts for your git account. Thank @davorpa

#!/bin/bash

# silent prompt
read -p 'GIT profile: ' profile

# switch
case $profile in
  superman)
    git config user.email "[email protected]"
    git config user.name "superman" 
    git config user.signingKey "superman_gpg_public_key"
    ;;
  oanhnn)
    git config user.email "[email protected]"
    git config user.name "oanhnn" 
    git config user.signingKey "oanhnn_gpg_public_key"
    ;;
  # default case: raise error
  *)
    >&2 echo "ERR: Unknown profile: $profile"
    exit 1
esac
@mihokpeter
Copy link

Hi there! Are any of you guys using this setup also using Fork as a git client or GUI for git? I am asking this, because I have some problems with fetching/pull/pushing my personal repo.

Here's my setup of .ssh/config file:

Work github account: peter.mihok-work

Host github.com
HostName github.com
IdentityFile ~/.ssh/id_work
IdentitiesOnly yes
UseKeychain yes
AddKeysToAgent yes
ControlMaster no

Personal github account: mihokpeter

Host github.com-mihokpeter
HostName github.com
IdentityFile ~/.ssh/id_mihokpeter
IdentitiesOnly yes
UseKeychain yes
AddKeysToAgent yes
ControlMaster no

What I don't understand is that even-thought my remote origin url is set either [email protected]:something/file.git or [email protected]:mihokpeter/file.git. In my personal repo I also added git config user.email and git config user.name. While using Fork I can easily push/pull/etc.. on my work branch, but I can't do none of this on my personal one. However, I can do all of those in terminal in my personal branch. So, with that said I think my ssh must be setup correctly (as those git commands are working) + I can see correct names being printed out in terminal after running ssh -T [email protected] and ssh -T [email protected].

Any ideas what can be wrong? I am really struggling here and I would appreciate any help!

@oanhnn
Copy link
Author

oanhnn commented Dec 15, 2023

@mihokpeter
You should ensure that your repository's remote origin URL is

$ git remote -v
origin [email protected]:mihokpeter/file.git (fetch)
origin [email protected]:mihokpeter/file.git (push)

Please look at the 2nd dot of step 5 in this gist.

@y-he2
Copy link

y-he2 commented Dec 22, 2023

This is super! However I couldnt get the "ssh -T" verify step to work without adding:

Host git@...
        ...
	User git
	...

So something to be awared maybe.

@oanhnn
Copy link
Author

oanhnn commented Dec 22, 2023

@y-he2 Can you show debug log (ssh -T git@github-alias) in case Host github-alias?

@y-he2
Copy link

y-he2 commented Dec 22, 2023

@y-he2 Can you show debug log (ssh -T git@github-alias) in case Host github-alias?

Heres what I could dig up from log with ChatGPT:
(Without "User git") It seems with "ssh -v HostName" even the SHA is matching, but it just give:
...
debug1: Authentications that can continue: publickey
debug1: No more authentication methods to try.
my_os_username @ github.com: Permission denied (publickey).

@oanhnn
Copy link
Author

oanhnn commented Dec 23, 2023

@y-he2
In your case, ssh will use a username from the logged-in user in the shell.

Host github-alias
   HostName github.com
   IdentityFile ~/.ssh/account1_private_key
   IdentitiesOnly yes
oanhnn@localhost:~$ ssh -vT github-alias
oanhnn@localhost:~$ ssh -vT [email protected]

Two commands have the same effect.
You should set it up one of two ways.

1 (your solution)

Host github-alias
   HostName github.com
   User git
   IdentityFile ~/.ssh/account1_private_key
   IdentitiesOnly yes
ssh -vT github-alias

2 (like my guide):

Host github-alias
   HostName github.com
   IdentityFile ~/.ssh/account1_private_key
   IdentitiesOnly yes
ssh -vT git@github-alias

@y-he2
Copy link

y-he2 commented Dec 24, 2023

@y-he2 In your case, ssh will use a username from the logged-in user in the shell.

Host github-alias
   HostName github.com
   IdentityFile ~/.ssh/account1_private_key
   IdentitiesOnly yes
oanhnn@localhost:~$ ssh -vT github-alias
oanhnn@localhost:~$ ssh -vT [email protected]

Two commands have the same effect. You should set it up one of two ways.

1 (your solution)

Host github-alias
   HostName github.com
   User git
   IdentityFile ~/.ssh/account1_private_key
   IdentitiesOnly yes
ssh -vT github-alias

2 (like my guide):

Host github-alias
   HostName github.com
   IdentityFile ~/.ssh/account1_private_key
   IdentitiesOnly yes
ssh -vT git@github-alias

Ah that "git@" is obviously what I have been missing, thanks for the clarification!

@oanhnn
Copy link
Author

oanhnn commented Jan 12, 2024

@viktorianer
Copy link

👍 That solution is good. But the only issue is that typing that command is somewhat long and tiring.

That is nota problem at all. Just add an alias for this command, a short one! ☺️

@gentunian
Copy link

problem with this is that only allows you to use your keys for cloning. But it won't work for installing dependencies that points to [email protected]/some/repo.

@alwaisy
Copy link

alwaisy commented Feb 3, 2024

Thanks bunch it worked for me. Saved my time. Stay happy and posting amazing stuff.

@smali-kazmi
Copy link

please add one thing in your gist suppose there is an github-superman account so you have to update your package.json like this

{
  "dependencies": {
      ......
      ......
      testRepo: "git+ssh://git@github-superman:org/testRepo.git#main"
  }
}

@IbroRebronja
Copy link

Very useful!

@David7ce
Copy link

David7ce commented Apr 2, 2024

Now is fixed. (I had the same Host I misunderstood, and put the same Hostname instead of the same Host.
The Host must be differ.

NOTE: If you use any account frequently, you should use the default hostname (github.com)

I have a problem, I have configured the config and add the pair of SSH keys both locally (to agent) and the remote server (GitHub) to two of my GitHub accounts. The pair of keys works fine independently if only have one pair of keys (moving the other outside), but if I have the two pairs of keys in the ~/.ssh/ the test only show me

ssh -T [email protected]
Hi <other-user> ! You've successfully authenticated, but GitHub does not provide shell access.

Here's is my config, I have two "Host github.com" but this should work fine and I think I have used in the past.

# Default github account: david7ce
Host github.com
   HostName github.com
   User git
   IdentityFile ~/.ssh/david7ce

# Second github account: <other-user> 
Host github.com
   HostName github.com
   User git
   IdentityFile ~/.ssh/<other-user> 

@IbroRebronja
Copy link

IbroRebronja commented Apr 2, 2024

You have two keys for the same door, but they're getting mixed up. Let's label one key for your main account and the other for your second account, so each key knows which door to open.

# Default github account: david7ce
Host github.com
   HostName github.com
   User git
   IdentityFile ~/.ssh/david7ce

# Second github account: <other-user> 
Host github-other
   HostName github.com
   User git
   IdentityFile ~/.ssh/<other-user>

@David7ce
Copy link

David7ce commented Apr 3, 2024

@IbroRebronja yes that was the issue, thanks for explanation

@IvanildoBarauna
Copy link

Thanks @oanhnn!

@mobeigi
Copy link

mobeigi commented Aug 8, 2024

Seems like an okay solution, although its a bit annoying to have aliases like github_personal when it should clearly be github.com.

I believe other alternatives exist which may be nicer:

  • Aliases or commands to load / unload the right SSH key into your SSH agent
  • Aliases or commands to export GIT_SSH_COMMAND variable (see here)

That way, usage would be something like:

git_work   // trigger alias to set GIT_SSH_COMMAND to work SSH key
git clone [email protected]:Company/Project
git_me  // trigger alias to set GIT_SSH_COMMAND to personal SSH key
git clone [email protected]:Personal/Project

All the repos have the correct hostname, your .ssh config is correct and all you need to do is remember to trigger the alias as you hop between different projects. If you get it wrong you get permission denied or not found so its simple to then remember and switch to the right one. Feels more correct to me.

@oanhnn
Copy link
Author

oanhnn commented Aug 9, 2024

@mobeigi Great idea.
You can make a bash script git-me.sh

#!/usr/bin/env bash

SSH_PRIVATE_KEY=~/.ssh/personal_private_key.pem

GIT_SSH_COMMAND="ssh -i $SSH_PRIVATE_KEY -o IdentitiesOnly=yes" git $@

And use it for personal projects.

git clone [email protected]:Company/Project.git
git-me.sh clone [email protected]:Personal/Project.git

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