Warum das überhaupt eine Einrichtung braucht
Jede GitHub-Verbindung geht an denselben Host mit demselben Benutzer, git. GitHub unterscheidet Konten nur am vorgelegten Schlüssel, und ssh hört beim ersten Schlüssel auf, den der Server akzeptiert. Sie brauchen also eine Möglichkeit, festzulegen, welcher Schlüssel für welches Repository gilt. Host-Aliase sind der übliche Weg.
1. Ein Schlüssel pro Konto
ssh-keygen -t ed25519 -C "personal" -f ~/.ssh/id_ed25519_personal
ssh-keygen -t ed25519 -C "work" -f ~/.ssh/id_ed25519_work
Fügen Sie jede .pub-Datei ihrem Konto hinzu, wie unter Schlüssel zu GitHub hinzufügen.
2. Ein Alias für jedes Konto 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
Prüfen Sie, wohin ein Alias aufgelöst wird, ohne sich zu verbinden:
ssh -G github-work | grep -E '^(hostname|user|identityfile|identitiesonly) '
Testen Sie dann jeden einzeln. Er sollte Sie mit dem richtigen Benutzernamen begrüßen:
ssh -T git@github-personal
ssh -T git@github-work
Warum IdentitiesOnly wichtig ist
Ohne es probiert ssh auch jeden Schlüssel in Ihrem Agent. In unserem Test wurde der in der Konfiguration genannte Schlüssel zuerst versucht. Wurde er aber abgelehnt, ging ssh zu einem anderen Schlüssel aus dem Agent über und meldete sich ohne Fehler als das andere Konto an. So landet ein Push unter dem falschen Namen, oder ein Repository scheint zu fehlen. Mit IdentitiesOnly yes scheiterte derselbe Test mit Permission denied, und das ist, was Sie wollen. Das verhindert außerdem Too many authentication failures, wenn Ihr Agent viele Schlüssel enthält.
3. Den Alias in der Adresse verwenden
Ersetzen Sie github.com durch den Alias:
git clone git@github-work:org/repo.git
Für ein bereits geklontes Repository:
git remote set-url origin git@github-work:org/repo.git
Damit Sie die von GitHub kopierten Adressen nicht ändern müssen, kann Git sie für eine Organisation umschreiben:
git config --global url."git@github-work:org/".insteadOf "git@github.com:org/"
4. Der richtige Name an Ihren Commits
Der SSH-Schlüssel entscheidet, wer pusht. Ihre Commits tragen, was user.email sagt, und das ist eine separate Einstellung. Halten Sie Arbeits-Repositories in einem Ordner und tragen Sie dies in ~/.gitconfig ein:
[user]
name = Your Name
email = you@example.com
[includeIf "gitdir:~/work/"]
path = ~/.gitconfig-work
Und in ~/.gitconfig-work:
[user]
email = you@work.example.com
Lassen Sie den abschließenden Schrägstrich in gitdir:~/work/ stehen, denn er sorgt dafür, dass alles darin passt. Prüfen Sie es innerhalb eines Repositorys:
cd ~/work/some-repo
git config user.email
Führen Sie das innerhalb eines Repositorys aus: In unserem Test zeigte der reine Ordner ~/work weiterhin die globale E-Mail, weil die Bedingung vom Ort des Repositorys abhängt.
Alternative: den Schlüssel pro Ordner wählen, ohne Aliase
Tragen Sie den Schlüssel in dieselbe Include-Datei ein und behalten Sie die normalen github.com-Adressen:
[core]
sshCommand = ssh -i ~/.ssh/id_ed25519_work -o IdentitiesOnly=yes
Das gilt erst, wenn Git in einem Repository in diesem Ordner ist. Beim ersten Clone müssen Sie den Schlüssel also von Hand setzen, was auch die dokumentierte einmalige Methode von GitHub ist:
GIT_SSH_COMMAND='ssh -i ~/.ssh/id_ed25519_work -o IdentitiesOnly=yes' git clone git@github.com:org/repo.git
Möchten Sie lieber anhand der Adresse des Repositorys statt seines Ordners zuordnen, akzeptiert Git 2.36 und neuer auch Bedingungen wie [includeIf "hasconfig:remote.*.url:git@github-work:*/**"].
Wenn etwas schiefgeht
- "Repository not found" trotz richtiger Adresse. Vermutlich sind Sie als das andere Konto authentifiziert. Führen Sie
ssh -Tmit dem Alias aus und lesen Sie den Namen. - Welcher Schlüssel wirklich verwendet wird.
ssh -vT git@github-workzeigt jeden angebotenen Schlüssel. - Permission denied. Siehe Permission denied (publickey) mit Git.
Fragen
Kann ich für beide Konten denselben Schlüssel verwenden?
Nein. GitHub lehnt einen Schlüssel ab, der schon bei einem anderen Konto hinterlegt ist, mit dem Fehler Key already in use.
Brauche ich den Alias noch, wenn ich core.sshCommand nutze?
Nein. Eines von beiden reicht, um den Schlüssel auszuwählen. Der Alias ist in der Remote-Adresse sichtbar, und core.sshCommand behält die normale Adresse github.com, was für Skripte praktisch ist, die sie erwarten.
Quellen
- Managing multiple accounts, GitHub Docs
- Error: Key already in use, GitHub Docs
- git-config, bedingte Includes
- ssh_config(5), OpenBSD-Handbuch