Perché serve una configurazione
Ogni connessione a GitHub va allo stesso host con lo stesso utente, git. GitHub distingue gli account solo dalla chiave che presenti, e ssh si ferma alla prima chiave che il server accetta. Ti serve quindi un modo per dire quale chiave usare per quale repository. Gli alias Host sono il metodo abituale.
1. Una chiave per account
ssh-keygen -t ed25519 -C "personal" -f ~/.ssh/id_ed25519_personal
ssh-keygen -t ed25519 -C "work" -f ~/.ssh/id_ed25519_work
Aggiungi ogni file .pub al suo account, come in aggiungere una chiave a GitHub.
2. Un alias per ciascuno in ~/.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
Controlla a cosa si risolve un alias, senza connetterti:
ssh -G github-work | grep -E '^(hostname|user|identityfile|identitiesonly) '
Poi prova ciascuno. Deve salutarti con il nome utente giusto:
ssh -T git@github-personal
ssh -T git@github-work
Perché IdentitiesOnly conta
Senza, ssh prova anche tutte le chiavi presenti nel tuo agent. Nel nostro test la chiave indicata nella configurazione veniva provata per prima. Ma quando quella chiave era rifiutata, ssh passava a un'altra chiave dell'agent e faceva il login come l'altro account, senza alcun errore. È così che un push finisce sotto il nome sbagliato, o un repository sembra mancare. Con IdentitiesOnly yes, lo stesso test falliva con Permission denied, che è ciò che vuoi. Evita anche Too many authentication failures quando l'agent contiene molte chiavi.
3. Usa l'alias nell'indirizzo
Sostituisci github.com con l'alias:
git clone git@github-work:org/repo.git
Per un repository che hai già clonato:
git remote set-url origin git@github-work:org/repo.git
Per non dover cambiare gli indirizzi che copi da GitHub, Git può riscriverli per una singola organizzazione:
git config --global url."git@github-work:org/".insteadOf "git@github.com:org/"
4. Il nome giusto nei tuoi commit
La chiave SSH decide chi fa il push. I tuoi commit riportano ciò che dice user.email, che è un'impostazione separata. Tieni i repository di lavoro in una cartella e aggiungi questo a ~/.gitconfig:
[user]
name = Your Name
email = you@example.com
[includeIf "gitdir:~/work/"]
path = ~/.gitconfig-work
E in ~/.gitconfig-work:
[user]
email = you@work.example.com
Mantieni la barra finale in gitdir:~/work/, che è ciò che fa corrispondere tutto il contenuto della cartella. Verifica dall'interno di un repository:
cd ~/work/some-repo
git config user.email
Eseguilo dentro un repository: nel nostro test, la semplice cartella ~/work mostrava ancora l'email globale, perché la condizione dipende dalla posizione del repository.
Alternativa: scegliere la chiave per cartella, senza alias
Metti la chiave nello stesso file incluso e mantieni i normali indirizzi github.com:
[core]
sshCommand = ssh -i ~/.ssh/id_ed25519_work -o IdentitiesOnly=yes
Si applica solo quando Git è dentro un repository di quella cartella. Quindi il primo clone richiede di impostare la chiave a mano, che è anche il metodo una tantum documentato da GitHub:
GIT_SSH_COMMAND='ssh -i ~/.ssh/id_ed25519_work -o IdentitiesOnly=yes' git clone git@github.com:org/repo.git
Se preferisci basarti sull'indirizzo del repository invece che sulla cartella, Git 2.36 e successivi accettano anche condizioni come [includeIf "hasconfig:remote.*.url:git@github-work:*/**"].
Se qualcosa va storto
- "Repository not found" con l'indirizzo giusto. Probabilmente sei autenticato come l'altro account. Esegui
ssh -Tcon l'alias e leggi il nome. - Quale chiave viene usata davvero.
ssh -vT git@github-workstampa ogni chiave che offre. - Permission denied. Vedi Permission denied (publickey) con Git.
Domande
Posso usare una sola chiave per entrambi gli account?
No. GitHub rifiuta una chiave che è già su un altro account, con l'errore Key already in use.
Mi serve ancora l'alias se uso core.sshCommand?
No. Uno dei due basta per scegliere la chiave. L'alias è visibile nell'indirizzo del remote, mentre core.sshCommand mantiene il normale indirizzo github.com, comodo per gli script che lo aspettano.
Fonti
- Gestire più account, GitHub Docs
- Error: Key already in use, GitHub Docs
- git-config, inclusioni condizionali
- ssh_config(5), manuale OpenBSD