I have 2 different github accounts, 1 for work and 1 for personal projects. On my laptop, I created 2 different directories to clone my Github repositories:
Perso: /Users/pierre-alexandre/Documents/perso
Work: /Users/pierre-alexandre/Documents/work
Then, I generated 2 different SSH keys on /Users/pierre-alexandre/.ssh
and added each .pub key on their respective Github repository. At the end this is what my /Users/pierre-alexandre/.ssh
folder looks like:
id_perso id_perso.pub id_work id_work.pub known_hosts
What I have done after, is:
ssh-add ~/.ssh/id_work
ssh-add ~/.ssh/id_perso
Then, I created a new file ~/.gitconfig
[includeIf "gitdir:~/Documents/perso/"]
path = ~/.gitconfig-perso
[includeIf "gitdir:~/Documents/servier/"]
path = ~/.gitconfig-servier
After that, I created 2 different other files and I make sure my name correspond to my Github username and the email correspond to my Github email the one I use to generate my SSH key:
~/.gitconfig-work
[user]
name = pamousset35
email = work-email
~/.gitconfig-perso
[user]
name = Pierre-Alexandre35
email = [email protected]
My issue is the following: I am able to interact with my work Github and but with my personnal github, I always have this issue when I am trying to push
or pull
:
pwd
/Users/pierre-alexandre/Documents/perso/pierre-alexandre.io
git pull
error log:
[email protected]: Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
github config using git config -l
(under this same directory)
credential.helper=osxkeychain
includeif.gitdir:~/Documents/perso/.path=~/.gitconfig-perso
user.name=Pierre-Alexandre35
[email protected]
includeif.gitdir:~/Documents/servier/.path=~/.gitconfig-servier
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
core.precomposeunicode=true
[email protected]:Pierre-Alexandre35/pierre-alexandre.io.git
remote.origin.fetch= refs/heads/*:refs/remotes/origin/*
branch.develop.remote=origin
branch.develop.merge=refs/heads/develop
Then I also typed: ssh -vT [email protected]
OpenSSH_8.1p1, LibreSSL 2.7.3
debug1: Reading configuration data /Users/pierre-alexandre/.ssh/config
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 47: Applying options for *
debug1: Connecting to github.com port 22.
debug1: Connection established.
debug1: identity file /Users/pierre-alexandre/.ssh/id_rsa type -1
debug1: identity file /Users/pierre-alexandre/.ssh/id_rsa-cert type -1
debug1: identity file /Users/pierre-alexandre/.ssh/id_dsa type -1
debug1: identity file /Users/pierre-alexandre/.ssh/id_dsa-cert type -1
debug1: identity file /Users/pierre-alexandre/.ssh/id_ecdsa type -1
debug1: identity file /Users/pierre-alexandre/.ssh/id_ecdsa-cert type -1
debug1: identity file /Users/pierre-alexandre/.ssh/id_ed25519 type -1
debug1: identity file /Users/pierre-alexandre/.ssh/id_ed25519-cert type -1
debug1: identity file /Users/pierre-alexandre/.ssh/id_xmss type -1
debug1: identity file /Users/pierre-alexandre/.ssh/id_xmss-cert type -1
debug1: Local version string SSH-2.0-OpenSSH_8.1
debug1: Remote protocol version 2.0, remote software version babeld-a73e1397
debug1: no match: babeld-a73e1397
debug1: Authenticating to github.com:22 as 'git'
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: algorithm: curve25519-sha256
debug1: kex: host key algorithm: ecdsa-sha2-nistp256
debug1: kex: server->client cipher: [email protected] MAC: <implicit> compression: none
debug1: kex: client->server cipher: [email protected] MAC: <implicit> compression: none
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: ecdsa-sha2-nistp256 SHA256:p2QAMXNIC1TJYWeIOttrVc98/R1BUFWu3/LiyKgUfQM
debug1: Host 'github.com' is known and matches the ECDSA host key.
debug1: Found key in /Users/pierre-alexandre/.ssh/known_hosts:1
debug1: rekey out after 134217728 blocks
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: rekey in after 134217728 blocks
debug1: Will attempt key: /Users/pierre-alexandre/.ssh/id_rsa
debug1: Will attempt key: /Users/pierre-alexandre/.ssh/id_dsa
debug1: Will attempt key: /Users/pierre-alexandre/.ssh/id_ecdsa
debug1: Will attempt key: /Users/pierre-alexandre/.ssh/id_ed25519
debug1: Will attempt key: /Users/pierre-alexandre/.ssh/id_xmss
debug1: SSH2_MSG_EXT_INFO received
debug1: kex_input_ext_info: server-sig-algs=<[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],ssh-ed25519,ecdsa-sha2-nistp521,ecdsa-sha2-nistp384,ecdsa-sha2-nistp256,rsa-sha2-512,rsa-sha2-256,ssh-rsa,ssh-dss>
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey
debug1: Next authentication method: publickey
debug1: Trying private key: /Users/pierre-alexandre/.ssh/id_rsa
debug1: Trying private key: /Users/pierre-alexandre/.ssh/id_dsa
debug1: Trying private key: /Users/pierre-alexandre/.ssh/id_ecdsa
debug1: Trying private key: /Users/pierre-alexandre/.ssh/id_ed25519
debug1: Trying private key: /Users/pierre-alexandre/.ssh/id_xmss
debug1: No more authentication methods to try.
[email protected]: Permission denied (publickey)
Then eval "$(ssh-agent -s)"
Agent pid 21213
And ssh-add -l
The agent has no identities.
CodePudding user response:
Git just runs ssh
to connect to a host. Once connected, Git has that ssh
run an appropriate Git command on their end, to handle the fetch or push operation. But the entire authentication process—determining who you are and deciding whether you have access—is wholly up to ssh and Git plays no real part in this process.
Your ssh -Tv
is therefore the crucial debug output here. We see that your connection to github fails to authenticate as you, after trying these keys:
debug1: Trying private key: /Users/pierre-alexandre/.ssh/id_rsa
debug1: Trying private key: /Users/pierre-alexandre/.ssh/id_dsa
debug1: Trying private key: /Users/pierre-alexandre/.ssh/id_ecdsa
debug1: Trying private key: /Users/pierre-alexandre/.ssh/id_ed25519
debug1: Trying private key: /Users/pierre-alexandre/.ssh/id_xmss
Note that it never tried any public keys. You need to have your ssh offer, to GitHub, the correct public key.
At this point, there's another problem looming. Your URL is:
[email protected]:Pierre-Alexandre35/pierre-alexandre.io.git
That is, you're going to have Git ask to log in as user git
on host github.com
. You have no ~/.ssh/config
, so there is no magic override: your ssh will connect to github.com
and ask to log in as git
and then offer the standard set of ssh keys. But you want an override: you want to connect to github.com
and ask to log in as git
, but then you want ssh to:
- send the
id_perso
public key if and only if you're coming from a personal repository, or - send the
id_work
public key if and only if you're coming from a work repository
and ssh has no idea which kind of repository you're coming from.
You need to smuggle in the kind of repository somehow—ideally, in a clever way. We'll come back to clever in a moment, but let's assume for now that you just use git remote set-url origin
in each work repository to change the log-in part of the URL from [email protected]
to git@gh-work
, and the log-in part of the URL for personal repositories to git@gh-perso
.
Then, in your ~/.ssh/config
file, you can list the following:
Host gh-work
Hostname github.com
IdentityFile ~/.ssh/id_work.pub
IdentitiesOnly yes
Host gh-perso
Hostname github.com
IdentityFile ~/.ssh/id_perso.pub
IdentitiesOnly yes
This configures ssh, quite independent of Git, so that when you run ssh git@gh-perso
, for instance, you tell your ssh that it should:
- connect to
github.com
(replacinggh-perso
); - try the
id_perso.pub
file as a key; - don't try anything but the listed
IdentityFile
s (you can list more than one), i.e., skip the standard files.
So when Git asks ssh to connect to git@gh-perso
, ssh actually tries to connect to github.com
.
(As a side note, if you add User git
to the Host
and IdentityFile
and so on section, you can leave off the git@
part. That's not required, but it's kind of convenient.)
Note: sometimes you may or must list the private key file, not the public key file. Sometimes you must list only the public key file. This seems to depend on agent version and/or ssh version. Work with ssh -Tv [email protected]
until you get this part working correctly, then go back to the Git side of things.
Making this clever and automatic through Git includeIf
Git has a trick where it will rewrite URLs at the "last moment", before connecting with fetch or push. Given any URL, Git looks for insteadOf
entries. This is explained in How to convert `git:` urls to `http:` urls for instance, but we can use it to rewrite:
ssh://github.com/Pierre-Alexandre35/pierre-alexandre.io.git
into:
ssh://gh-perso/Pierre-Alexandre35/pierre-alexandre.io.git
We simply set the insteadOf
up with:
[url "ssh://gh-perso/"]
insteadOf = ssh://github.com/
for instance. (I have not actually tested all the insteadOf stuff, and you may need to fiddle with the details a bit, depending on whether you use git@
and whether you use the [email protected]:
form rather than the ssh://[email protected]
form.) Put the appropriate rewrite rules in each of the included personal and work config files, and now github.com
URLs automatically become gh-perso
or gh-work
URLs, which then trigger the stuff you set up with ssh.