Come usare più account GitHub con SSH

GitHub riconosce il tuo account dalla chiave SSH, quindi usa una chiave per account. In ~/.ssh/config, crea per ciascuno un alias Host con HostName github.com, il suo IdentityFile e IdentitiesOnly yes. Poi clona con l'alias, come in git clone git@github-work:org/repo.git. Usa includeIf in Git per impostare l'email giusta per cartella.

Aggiornata il . Configurazione, Git e comportamento dell'agent provati con OpenSSH e Git 2.47 contro un server SSH locale impostato per comportarsi come GitHub: un solo utente git, con ogni chiave associata a un nome account diverso, inclusi clone e push reali.

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 -T con l'alias e leggi il nome.
  • Quale chiave viene usata davvero. ssh -vT git@github-work stampa 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

Altro in Configurazione e tanti server

Tutte le guide