Por qué esto necesita configuración
Toda conexión a GitHub va al mismo host con el mismo usuario, git. GitHub distingue las cuentas solo por la clave que presentas, y ssh se detiene en la primera clave que el servidor acepta. Necesitas, por tanto, una forma de indicar qué clave usar para cada repositorio. Los alias de Host son la forma habitual.
1. Una clave por cuenta
ssh-keygen -t ed25519 -C "personal" -f ~/.ssh/id_ed25519_personal
ssh-keygen -t ed25519 -C "work" -f ~/.ssh/id_ed25519_work
Añade cada archivo .pub a su cuenta, como en añadir una clave a GitHub.
2. Un alias para cada una en ~/.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
Comprueba a qué se resuelve un alias, sin conectar:
ssh -G github-work | grep -E '^(hostname|user|identityfile|identitiesonly) '
Luego prueba cada uno. Debería saludarte con el nombre de usuario correcto:
ssh -T git@github-personal
ssh -T git@github-work
Por qué importa IdentitiesOnly
Sin ello, ssh también prueba todas las claves de tu agente. En nuestra prueba, la clave indicada en la configuración se probó primero. Pero cuando esa clave fue rechazada, ssh pasó a otra clave del agente e inició sesión como la otra cuenta, sin ningún error. Así es como un push acaba con el nombre equivocado, o un repositorio parece no existir. Con IdentitiesOnly yes, la misma prueba falló con Permission denied, que es lo que quieres. También evita Too many authentication failures cuando tu agente tiene muchas claves.
3. Usa el alias en la dirección
Sustituye github.com por el alias:
git clone git@github-work:org/repo.git
Para un repositorio que ya clonaste:
git remote set-url origin git@github-work:org/repo.git
Para no tener que cambiar las direcciones que copias de GitHub, Git puede reescribirlas para una organización:
git config --global url."git@github-work:org/".insteadOf "git@github.com:org/"
4. El nombre correcto en tus commits
La clave SSH decide quién hace el push. Tus commits llevan lo que diga user.email, que es un ajuste aparte. Mantén los repositorios de trabajo en una carpeta y añade esto a ~/.gitconfig:
[user]
name = Your Name
email = you@example.com
[includeIf "gitdir:~/work/"]
path = ~/.gitconfig-work
Y en ~/.gitconfig-work:
[user]
email = you@work.example.com
Conserva la barra final en gitdir:~/work/, que es lo que hace que coincida con todo lo que hay dentro. Compruébalo desde dentro de un repositorio:
cd ~/work/some-repo
git config user.email
Ejecútalo dentro de un repositorio: en nuestra prueba, la carpeta ~/work a secas seguía mostrando el email global, porque la condición depende de la ubicación del repositorio.
Alternativa: elegir la clave por carpeta, sin alias
Pon la clave en el mismo archivo incluido y conserva las direcciones normales de github.com:
[core]
sshCommand = ssh -i ~/.ssh/id_ed25519_work -o IdentitiesOnly=yes
Solo se aplica cuando Git está dentro de un repositorio de esa carpeta. Así que el primer clone necesita la clave indicada a mano, que es también el método puntual documentado por GitHub:
GIT_SSH_COMMAND='ssh -i ~/.ssh/id_ed25519_work -o IdentitiesOnly=yes' git clone git@github.com:org/repo.git
Si prefieres coincidir por la dirección del repositorio y no por su carpeta, Git 2.36 y posteriores también aceptan condiciones como [includeIf "hasconfig:remote.*.url:git@github-work:*/**"].
Si algo sale mal
- "Repository not found" con la dirección correcta. Probablemente estás autenticado como la otra cuenta. Ejecuta
ssh -Tcon el alias y lee el nombre. - Qué clave se usa realmente.
ssh -vT git@github-workimprime cada clave que ofrece. - Permission denied. Mira Permission denied (publickey) con Git.
Preguntas
¿Puedo usar una misma clave para las dos cuentas?
No. GitHub rechaza una clave que ya está en otra cuenta, con el error Key already in use.
¿Sigo necesitando el alias si uso core.sshCommand?
No. Con cualquiera de los dos basta para elegir la clave. El alias es visible en la dirección del remoto, y core.sshCommand mantiene la dirección normal de github.com, que resulta cómoda para scripts que la esperan.
Fuentes
- Gestionar varias cuentas, documentación de GitHub
- Error: Key already in use, documentación de GitHub
- git-config, inclusiones condicionales
- ssh_config(5), manual de OpenBSD