Home > other >  Separate gitconfig by directory
Separate gitconfig by directory

Time:11-20

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 (replacing gh-perso);
  • try the id_perso.pub file as a key;
  • don't try anything but the listed IdentityFiles (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.

  • Related