Pourquoi cela demande une configuration
Chaque connexion à GitHub va vers le même hôte avec le même utilisateur, git. GitHub ne distingue les comptes que par la clé que vous présentez, et ssh s'arrête à la première clé que le serveur accepte. Il faut donc un moyen d'indiquer quelle clé utiliser pour quel dépôt. Les alias Host sont la solution habituelle.
1. Une clé par compte
ssh-keygen -t ed25519 -C "personal" -f ~/.ssh/id_ed25519_personal
ssh-keygen -t ed25519 -C "work" -f ~/.ssh/id_ed25519_work
Ajoutez chaque fichier .pub à son compte, comme dans ajouter une clé à GitHub.
2. Un alias pour chacun dans ~/.ssh/config
Host github-personal
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_personal
IdentitiesOnly yes
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_work
IdentitiesOnly yes
Vérifiez ce que devient un alias, sans se connecter :
ssh -G github-work | grep -E '^(hostname|user|identityfile|identitiesonly) '
Testez ensuite chacun. Il doit vous saluer avec le bon nom d'utilisateur :
ssh -T git@github-personal
ssh -T git@github-work
Pourquoi IdentitiesOnly compte
Sans cette option, ssh essaie aussi toutes les clés de votre agent. Dans notre test, la clé indiquée dans la configuration était essayée en premier. Mais quand cette clé était refusée, ssh passait à une autre clé de l'agent et se connectait avec l'autre compte, sans aucune erreur. C'est ainsi qu'un push se retrouve sous le mauvais nom, ou qu'un dépôt semble introuvable. Avec IdentitiesOnly yes, le même test a échoué avec Permission denied, ce qui est ce que l'on veut. Cela évite aussi Too many authentication failures quand votre agent contient beaucoup de clés.
3. Utiliser l'alias dans l'adresse
Remplacez github.com par l'alias :
git clone git@github-work:org/repo.git
Pour un dépôt déjà cloné :
git remote set-url origin git@github-work:org/repo.git
Pour éviter de modifier les adresses que vous copiez depuis GitHub, Git peut les réécrire pour une organisation :
git config --global url."git@github-work:org/".insteadOf "git@github.com:org/"
4. Le bon nom sur vos commits
La clé SSH décide qui pousse. Vos commits portent ce que dit user.email, qui est un réglage distinct. Gardez les dépôts de travail dans un même dossier et ajoutez ceci à ~/.gitconfig :
[user]
name = Your Name
email = you@example.com
[includeIf "gitdir:~/work/"]
path = ~/.gitconfig-work
Et dans ~/.gitconfig-work :
[user]
email = you@work.example.com
Gardez la barre oblique finale dans gitdir:~/work/ : c'est elle qui fait correspondre tout ce qui se trouve à l'intérieur. Vérifiez depuis l'intérieur d'un dépôt :
cd ~/work/some-repo
git config user.email
Lancez cette commande dans un dépôt : dans notre test, le simple dossier ~/work affichait toujours l'adresse e-mail globale, car la condition dépend de l'emplacement du dépôt.
Alternative : choisir la clé par dossier, sans alias
Mettez la clé dans le même fichier inclus, et gardez les adresses normales github.com :
[core]
sshCommand = ssh -i ~/.ssh/id_ed25519_work -o IdentitiesOnly=yes
Cela ne s'applique qu'une fois que Git se trouve dans un dépôt de ce dossier. Le premier clone demande donc de définir la clé à la main, ce qui est aussi la méthode ponctuelle documentée par GitHub :
GIT_SSH_COMMAND='ssh -i ~/.ssh/id_ed25519_work -o IdentitiesOnly=yes' git clone git@github.com:org/repo.git
Si vous préférez cibler l'adresse du dépôt plutôt que son dossier, Git 2.36 et les versions suivantes acceptent aussi des conditions comme [includeIf "hasconfig:remote.*.url:git@github-work:*/**"].
Si cela se passe mal
- "Repository not found" avec la bonne adresse. Vous êtes probablement authentifié avec l'autre compte. Lancez
ssh -Tavec l'alias et lisez le nom. - Quelle clé est vraiment utilisée.
ssh -vT git@github-workaffiche chaque clé proposée. - Permission denied. Voir Permission denied (publickey) avec Git.
Questions
Puis-je utiliser la même clé pour les deux comptes ?
Non. GitHub refuse une clé déjà associée à un autre compte, avec l'erreur Key already in use.
Ai-je encore besoin de l'alias si j'utilise core.sshCommand ?
Non. L'un ou l'autre suffit pour choisir la clé. L'alias est visible dans l'adresse du dépôt distant, alors que core.sshCommand garde l'adresse normale github.com, ce qui est pratique pour les scripts qui l'attendent.
Sources
- Gérer plusieurs comptes, GitHub Docs
- Error: Key already in use, GitHub Docs
- git-config, inclusions conditionnelles
- ssh_config(5), manuel OpenBSD