Использование нескольких SSH-ключей с Git и GitHub

Быстрые ссылки
- В чём проблема?
- Проверка конфигурации Git
- Редактирование ~/.ssh/config
- Устранение неполадок
В чём проблема?
При подключении к удалённому Git-серверу (например, GitHub) клиент аутентифицируется по HTTPS или SSH. При использовании SSH возможны ошибки, связанные с выбором ключа:
- Если SSH-ключа нет вообще, вы увидите:
Permission denied (publickey).и
fatal: Could not read from remote repository.Решение: сгенерировать SSH-ключ и добавить публичную часть в настройки аккаунта.
- Если ключ есть, но у вас несколько аккаунтов и ключи перепутались, вы можете увидеть похожее сообщение:
Permission to Username/Repository.git denied to otheraccount.и
fatal: Could not read from remote repository.В этом случае сервер принял SSH-ключ, но он привязан к другому аккаунту. То есть проблема не в отсутствии ключа, а в том, что на сервер отправился не тот ключ.
Почему это происходит: SSH-клиент выбирает ключи по собственным правилам (агент, порядок файлов в ~/.ssh, HostName и т. д.). Если не ограничить выбор с помощью конфигурации, сервер увидит неправильно аутентифицированного пользователя, и доступ будет отклонён.
Проверка конфигурации Git
Сначала убедитесь, что в локальном репозитории указаны правильные имя и почта (они влияют на коммиты, но не на SSH-аутентификацию):
git config --listУстановите локально для репозитория или глобально:
git config user.name "Имя"git config user.email "email@example.com"Если проблема только в имени/почте — этого достаточно. Но в большинстве случаев при ошибках доступа нужно править SSH-конфигурацию.
Редактирование ~/.ssh/config
Если у вас нет отдельного ключа для аккаунта, создайте его; если есть — поместите правильный файл в ~/.ssh и дайте понятное имя (например, ~/.ssh/github).
Создать новый ключ:
ssh-keygen -t rsa -f ~/.ssh/githubПример минимального и корректно отформатированного файла ~/.ssh/config с двумя ключами для одного хоста (github.com) — один ключ для «main», другой — для «old»:
Host main
HostName github.com
User git
IdentityFile ~/.ssh/github
IdentitiesOnly yes
Host old
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa
IdentitiesOnly yesПояснения:
- Host — псевдоним, который вы будете использовать в URL удалённого репозитория (см. ниже).
- HostName — реальный адрес сервера (github.com).
- User — имя пользователя SSH для GitHub (обычно git).
- IdentityFile — путь к приватному ключу.
- IdentitiesOnly yes — говорит SSH не пытаться использовать ключи из агента, если вы хотите строго контролировать, какой файл будет отправлен.
После добавления блока Host замените в настройках remote вашего репозитория домен github.com на псевдоним Host (в примере — main). Это принудительно выберет нужный ключ.
Удалить старый origin и добавить новый:
git remote remove origingit remote add origin git@main:username/repository.gitОбратите внимание: в URL указан не github.com, а main — это именно тот alias из ~/.ssh/config.
Примечание про права доступа к файлам
Убедитесь, что приватные ключи имеют корректные права доступа:
chmod 600 ~/.ssh/githubНа Windows используйте инструменты управления ключами, подходящие для вашей среды (OpenSSH, Pageant для PuTTY, Windows SSH agent).
Устранение неполадок
- Как проверить, какой ключ отправляется на сервер:
ssh -vT git@github.comВ подробном выводе (verbose) будет видно, какие ключи пробуются и какой из них принят. Если вы хотите принудительно указать ключ:
ssh -i ~/.ssh/github -vT git@github.com- Альтернатива для отладки с Git (на время сессии):
GIT_SSH_COMMAND='ssh -i ~/.ssh/github -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' git pushЭто заставит git в этой командной сессии использовать конкретный ключ.
- Проверка агента SSH:
ssh-add -lЕсли агент содержит ключи, они могут использоваться первыми. Добавьте нужный ключ в агент или используйте IdentitiesOnly в конфиге, чтобы игнорировать агент.
- Особенности Windows и GUI-клиентов
- На Windows есть несколько реализаций SSH (OpenSSH, PuTTY/Pageant). GUI-клиенты (Fork, Sourcetree, GitHub Desktop и проч.) могут использовать свой агент или системный. Проверьте настройки клиента и убедитесь, что он использует нужный ключ или системный агент.
- В Fork, например, клиент может по умолчанию брать ключ из Windows agent, а не из ~/.ssh. Проверьте настройки SSH в GUI.
Важно: путь к файлам и местонахождение конфигурационного файла могут отличаться в зависимости от среды (WSL, Cygwin, Git Bash, PowerShell). Учитывайте это при проверке.
Мини-методология: шаги для безопасной настройки нескольких ключей
- Сгенерируйте отдельный ключ для каждого аккаунта: ~/.ssh/github_main, ~/.ssh/github_work, ~/.ssh/id_rsa_personal.
- Настройте ~/.ssh/config с уникальными Host блоками для каждого ключа.
- Убедитесь, что в каждом репозитории remote указывает на нужный Host alias: git@host-alias:username/repo.git.
- Проверьте подключение командой ssh -vT и убедитесь, что сервер принимает нужный ключ.
- Зафиксируйте шаги в README команды или в личных заметках, чтобы другие разработчики воспроизводили ту же конфигурацию.
Контрольные сценарии (тест-кейсы)
- Тест 1: В репозитории с remote git@main:username/repo.git выполните ssh -vT git@main; ожидается, что SSH попробует и использует ключ ~/.ssh/github.
- Тест 2: Удалите все ключи из агента и попробуйте git push; при IdentitiesOnly yes должен использоваться только IdentityFile.
- Тест 3: В GUI-клиенте переключитесь на системный агент и проверьте, не перезаписывает ли он выбор ключа.
Рольные чек-листы
Разработчик:
- Сгенерировал ключ и добавил публичную часть в нужный аккаунт GitHub.
- Настроил ~/.ssh/config и проверил Host alias.
- Обновил remote репозиторий и сделал git push.
Владелец репозитория:
- Убедился, что публичный ключ добавлен в настройки аккаунта с нужными правами.
- При необходимости удалил старые ключи, которые больше не используются.
Системный администратор / DevOps:
- Настроил инструкции для команды по стандартизации имён ключей и конфига.
- Проверил наличие и настройки SSH-агента на CI/CD и серверах сборки.
Критерии приёмки
- Git push работает без ошибок доступа.
- В выводе ssh -v видно использование ожидаемого приватного ключа.
- Для каждого аккаунта в организации установлен отдельный ключ и прописан отдельный Host в конфиге.
Решения на случай, если метод не сработал
- Если SSH продолжает пробовать неправильные ключи, временно отключите агент (ssh-agent) и запустите ssh с флагом -i, чтобы убедиться, что проблема именно в выборе ключа.
- Если GUI-клиент игнорирует ~/.ssh/config, проверьте его документацию — у многих клиентов есть собственные настройки SSH.
- На CI/CD — проверьте, добавлен ли приватный ключ в секреты и правильно ли настроен агент на раннере.
Диаграмма принятия решения
flowchart TD
A[Начало: ошибка доступа] --> B{Ошибка: 'Permission denied 'publickey''?}
B -- Да --> C[Проверить наличие публичного ключа в аккаунте]
B -- Нет --> D{Сообщение: 'denied to otheraccount'?}
D -- Да --> E[Проверить ~/.ssh/config и remote URL]
D -- Нет --> F[Проверить сеть и URL репозитория]
E --> G[Заменить remote на git@host-alias:... и повторить]
C --> H[Создать ключ, добавить в аккаунт, проверить]
H --> G
F --> I[Проверить доступ по HTTPS или SSH вручную]Полезные команды и шпаргалка
- Создание ключа:
ssh-keygen -t rsa -f ~/.ssh/github - Просмотр списка ключей агента:
ssh-add -l - Отладка SSH:
ssh -vT git@github.com - Принудительный вызов SSH при push:
GIT_SSH_COMMAND='ssh -i ~/.ssh/github' git push - Права на приватный ключ:
chmod 600 ~/.ssh/github

Итог
Правильная настройка ~/.ssh/config и корректный remote URL решают большинство проблем с «неправильным» SSH-ключом. Тестируйте подключения с помощью ssh -vT и документируйте порядок настройки в вашей команде.
Важно: если вы работаете в разных средах (macOS, Linux, Windows, WSL), проверьте местоположение конфигурации и поведение агента в каждой из них.
Краткая памятка: один ключ — одна роль/аккаунт; Host alias в конфиге — выбор ключа; remote URL должен ссылаться на этот alias.
Похожие материалы
Несколько аккаунтов Skype: Multi Skype Launcher
Журнал для работы: повысить продуктивность
Персональные звуки уведомлений на Android
Скачивание шоу Hulu для офлайн‑просмотра
Microsoft Start: персонализированная новостная лента