59

I've set up two GitHub accounts, but I can't get ssh keys to work correctly. I've tried various configs.


Host github_username1
    HostName github.com
    IdentityFile ~/.ssh/rsa_1
    User username1
Host github_username2
    HostName github.com
    IdentityFile ~/.ssh/rsa_2
    User username2

git push:

Permission denied (publickey).
fatal: The remote end hung up unexpectedly

Works for username1:

Host github.com
    HostName github.com
    IdentityFile ~/.ssh/rsa_1
    User username1
Host github.com
    HostName github.com
    IdentityFile ~/.ssh/rsa_2
    User username2

git push at username2's repo:

ERROR: Permission to username2/repo.git denied to username1.
fatal: The remote end hung up unexpectedly

I've also tried git push with both IdentityFile and User settings under same Host. The output is the same as with the last config.

I think git automatically searches for Host "github.com" because the remote is such. It is said that Host can be anything you want (https://stackoverflow.com/a/3828682). Is there any way to change what Host from ssh config should specific repo use?

It would be ideal if I could solve this just from ~/.ssh/config.

1 Answer 1

78

Yes, only the section headers (the Host or Match lines) are searched for – everything else is only applied as a setting. In other words, if you connect to [email protected], OpenSSH will only look for a section titled Host bar.com.

So if you have Host github_username2, you must use this exact same "hostname" in your Git remotes as well. OpenSSH will not find this section if you use [email protected].

However, that is not what causes authentication failures. When connecting to GitHub via SSH, you must use git as your username – the server will recognize you based on the key alone. (In other words, the "git@" in "[email protected]" is actually the SSH username that GitHub uses – not some kind of URI scheme.)

So a correct SSH configuration would be:

Host github_username1
    Hostname github.com
    User git
    IdentityFile ~/.ssh/rsa_1
    IdentitiesOnly yes

Host github_username2
    Hostname github.com
    User git
    IdentityFile ~/.ssh/rsa_2
    IdentitiesOnly yes

with this Git configuration:

[remote "origin"]
    url = github_username1:username2/repo.git

(It doesn't matter where you specify the SSH username – you can have git@ in the URL, or you can have User git in .ssh/config, or both.)


Alternative Git configuration to automatically switch accounts depending on repo path:

  1. Create a file ~/.config/git/config.user1 containing:

    [url "github_username1:"]
        insteadOf = [email protected]:
    
  2. Create a config.user2 file that's the same except with "github_username2".

  3. In your main ~/.config/git/config file, tell Git to "include" one of the two files depending on which directory you're at:

    [includeIf "gitdir:~/projects/"]
        path = ~/.config/git/config.user1
    
    [includeIf "gitdir:~/src/work/"]
        path = ~/.config/git/config.user2
    
  4. Now, whenever you're at ~/src/work/, cloning anything from [email protected]:[etc] will automatically rewrite the URL to github_username2:[etc].

6
  • 7
    In some cases you might need to add IdentitiesOnly=yes on each host section to make sure ssh will only pick the chosen identity file and don't default / try anything else..
    – TCB13
    Dec 26, 2015 at 1:19
  • 1
    This solution is not foolproof, when you have submodules you are stuck with a broken .gitconfig
    – mars
    Mar 22, 2021 at 10:18
  • 2
    @TCB13 your hint about IdentitiesOnly just saved me after I couldn't figure out why my config hasn't been working. Thanks a lot! Sep 23, 2022 at 19:23
  • 1
    IdentitiesOnly was also required for me. Should be added to the main answer! Oct 5, 2022 at 11:45
  • 1
    An alternative to this answer is to use SSH config matchers, which allows matching a unique host + user combination. Oct 25, 2022 at 2:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .