544

ssh имеет опцию -i чтобы указать, какой файл закрытого ключа использовать при аутентификации:

-i identity_file

    Выбирает файл, из которого читается идентификатор (закрытый ключ) для аутентификации RSA или DSA.  По умолчанию используется ~/.ssh/identity для версии протокола 1 и ~/.ssh/id_rsa и ~/.ssh/id_dsa для версии протокола 2.  Файлы идентификации также могут быть указаны для каждого хоста в файле конфигурации.  Можно иметь несколько параметров -i (и несколько идентификаторов, указанных в файлах конфигурации).

Есть ли аналогичный способ сообщить git какой файл закрытого ключа использовать в системе с несколькими закрытыми ключами в каталоге ~/.ssh ?

16 ответов16

587

В ~/.ssh/config добавьте:

host github.com
 HostName github.com
 IdentityFile ~/.ssh/id_rsa_github
 User git

Теперь вы можете сделать git clone git@github.com:username/repo.git .

ПРИМЕЧАНИЕ. Убедитесь, что разрешения для IdentityFile равны 400.SSH будет неявным образом отклонять слишком читаемые ключи SSH. Это будет выглядеть как отказ от полномочий. Решение в этом случае:

chmod 400 ~/.ssh/id_rsa_github
268

Переменная среды GIT_SSH_COMMAND:

Начиная с версии Git 2.3.0, вы можете использовать переменную окружения GIT_SSH_COMMAND например:

GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa_example" git clone example

Обратите внимание, что -i иногда может быть переопределен вашим конфигурационным файлом, и в этом случае вы должны дать SSH пустой конфигурационный файл, например так:

GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa_example -F /dev/null" git clone example

Конфигурация core.sshCommand:

Начиная с Git версии 2.10.0, вы можете настроить это для репо или глобально, так что вам больше не нужно устанавливать переменную среды!

git config core.sshCommand "ssh -i ~/.ssh/id_rsa_example -F /dev/null"
git pull
git push
84

Нет прямого способа сообщить git какой закрытый ключ использовать, потому что он использует ssh для аутентификации в репозитории. Тем не менее, есть еще несколько способов достижения вашей цели:

Вариант 1: ssh-agent

Вы можете использовать ssh-agent для временной авторизации вашего закрытого ключа.

Например:

$ ssh-agent sh -c 'ssh-add ~/.ssh/id_rsa; git fetch user@host'

Вариант 2: GIT_SSH_COMMAND

Передайте аргументы ssh с помощью переменной среды GIT_SSH_COMMAND (Git 2.3.0+).

Например:

$ GIT_SSH_COMMAND='ssh -i ~/.ssh/id_rsa -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' \
  git clone user@host

Вы можете напечатать все это в одной строке - игнорируйте $ и пропустите \ .

Вариант 3: GIT_SSH

Передайте аргументы ssh, используя переменную среды GIT_SSH чтобы указать альтернативный двоичный файл ssh .

Например:

$ echo 'ssh -i ~/.ssh/id_rsa -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no $*' > ssh
$ chmod +x ssh
$ GIT_TRACE=1 GIT_SSH='./ssh' git clone user@host

Примечание. Вышеуказанные строки являются командными строками оболочки (терминала), которые вы должны вставить в свой терминал. Они создадут файл с именем ssh, сделают его исполняемым и (косвенно) выполнят его.

Примечание: GIT_SSH доступен с v0.99.4 (2005).

Вариант 4: ~/.ssh/config

Используйте файл ~/.ssh/config как предложено в других ответах, чтобы указать местоположение вашего личного ключа, например

Host github.com
  User git
  Hostname github.com
  IdentityFile ~/.ssh/id_rsa
32

Напишите скрипт, который вызывает ssh с нужными аргументами, и укажите имя файла скрипта в $GIT_SSH . Или просто поместите свою конфигурацию в ~/.ssh/config .

15

Если вы не хотите указывать переменные окружения каждый раз, когда вы запускаете git, не хотите другой скрипт-обертку, не запускаете ssh-agent(1) и не хотите загружать другой пакет только для этого, используйте git -remote-ext(1) внешний транспорт:

$ git clone 'ext::ssh -i $HOME/.ssh/alternate_id git.example.com %S /path/to/repository.git'
Cloning into 'repository'
(...)
$ cd repository
$ git remote -v
origin  ext::ssh -i $HOME/.ssh/alternate_id git.example.com %S /path/to/repository.git (fetch)
origin  ext::ssh -i $HOME/.ssh/alternate_id git.example.com %S /path/to/repository.git (push)

Я считаю это решение превосходным, потому что:

  • Это репозиторий / удаленный
  • Избегайте раздувания скриптов
  • Не нужен агент SSH - полезно, если вы хотите без присмотра клоны / push / pull (например, в cron)
  • Определенно, внешний инструмент не нужен
13

После моей борьбы с $GIT_SSH я хотел бы поделиться тем, что сработало для меня.

В моих примерах я предполагаю, что у вас есть ваш закрытый ключ, расположенный по адресу /home/user/.ssh/jenkins

Ошибка, которую следует избегать: значение GIT_SSH включает опции

$ export GIT_SSH="ssh -i /home/user/.ssh/jenkins"

или что-то подобное не удастся, так как git попытается выполнить значение в виде файла. По этой причине вы должны создать скрипт.

Рабочий пример сценария $ GIT_SSH /home/user/gssh.sh

Сценарий будет вызываться следующим образом:

$ $GIT_SSH [username@]host [-p <port>] <command>

Пример работы скрипта может выглядеть так:

#!/bin/sh
ssh -i /home/user/.ssh/jenkins $*

Обратите внимание на $* в конце, это важная часть.

Еще более безопасная альтернатива, которая предотвратит любой возможный конфликт с чем-либо в вашем файле конфигурации по умолчанию (плюс явное упоминание используемого порта):

#!/bin/sh
ssh -i /home/user/.ssh/jenkins -F /dev/null -p 22 $*

Предполагая, что скрипт находится в /home/user/gssh.sh , вы должны:

$ export GIT_SSH=/home/user/gssh.sh

и все будет работать.

10

Используйте пользовательскую конфигурацию хоста в ~/.ssh/config , например так:

Host gitlab-as-thuc  
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_rsa.thuc
    IdentitiesOnly yes

затем используйте свое собственное имя хоста следующим образом:

git remote add thuc git@gitlab-as-thuc:your-repo.git  
5

Вы можете просто использовать ssh-идент вместо создания своей собственной оболочки.

Вы можете прочитать больше на:https://github.com/ccontavalli/ssh-ident

Он загружает ssh-ключи по требованию при первой необходимости, один раз, даже с несколькими сеансами входа в систему, xterms или общими домами NFS.

С помощью крошечного файла конфигурации он может автоматически загружать разные ключи и сохранять их разделенными в разных агентах (для переадресации агентов) в зависимости от того, что вам нужно сделать.

4

У меня был клиент, которому нужна была отдельная учетная запись на github. Поэтому мне нужно было использовать отдельный ключ только для этого проекта.

Мое решение было добавить это в мой .zshrc / .bashrc:

alias infogit="GIT_SSH_COMMAND=\"ssh -i ~/.ssh/id_specialkey\" git $@"

Всякий раз, когда я хочу использовать git для этого проекта, я заменяю "infogit" на git:

infogit commit -am "Some message" && infogit push

Для меня это легче запомнить.

2

Мое решение было таким:

создать скрипт:

#!/bin/bash
KEY=dafault_key_to_be_used
PORT=10022 #default port...
for i in $@;do
   case $i in
    --port=*)
        PORT="${i:7}";;
    --key=*)KEY="${i:6}";;
   esac
done
export GIT_SSH_COMMAND="ssh -i $HOME/.ssh/${KEY} -p ${PORT}"
echo Command: $GIT_SSH_COMMAND

затем, когда вам нужно изменить запуск var:

. ./thescript.sh [--port=] [--key=]

Не забывайте лишнюю точку! это заставляет скрипт устанавливать окружение vars !! --key и --port не обязательны.

2

Поэтому я установил переменную GIT_SSH env в $HOME/bin/git-ssh .

Для того, чтобы моя конфигурация репозитория диктовала, какую идентификацию ssh использовать, мой файл ~/bin/git-ssh выглядит так:

#!/bin/sh
ssh -i $(git config --get ssh.identity) -F /dev/null -p 22 $*

Тогда у меня есть глобальная настройка git config:

$ git config --global ssh.identity ~/.ssh/default_id_rsa

И в любом git-репозитории я могу просто установить локальное значение git config ssh.identity :

$ git config --local ssh.identity ~/.ssh/any_other_id_rsa

Вуаля!

Если вы можете иметь разные адреса электронной почты для каждой личности, это становится еще проще, потому что вы можете просто назвать свои ключи после своих адресов электронной почты, а затем заставить git config user.email управлять выбором ключа в ~/bin/git-ssh как это:

#!/bin/sh
ssh -i $HOME/.ssh/$(git config --get user.email) -F /dev/null -p 22 $*
1

Как правило, вы хотите использовать ~/.ssh/config для этого. Просто соедините адреса серверов с ключами, которые вы хотите использовать для них, следующим образом:

Host github.com
  IdentityFile ~/.ssh/id_rsa.github
Host heroku.com
  IdentityFile ~/.ssh/id_rsa.heroku
Host *
  IdentityFile ~/.ssh/id_rsa

Host * обозначает любой сервер, поэтому я использую его для установки ~/.ssh/id_rsa в качестве ключа по умолчанию для использования.

1

Я основываюсь на @shellholic и этой ТАКОЙ ветке с несколькими тиками. Я использую GitHub в качестве примера и предполагаю, что у вас есть закрытый ключ в ~/.ssh/github (в противном случае см. Эту ветку SO) и что вы добавили открытый ключ в свой профиль GitHub (в противном случае см. Справку GitHub).

При необходимости создайте новый конфигурационный файл SSH в ~/.ssh/config и измените разрешения на 400

touch ~/.ssh/config
chmod 600 ~/.ssh/config

Добавьте это в файл ~/.ssh/config :

Host github.com
    IdentityFile ~/.ssh/github
    IdentitiesOnly yes

Если у вас уже есть удаленная настройка, вы можете удалить ее, в противном случае вам все равно может быть предложено ввести имя пользователя и пароль:

git remote rm origin

Затем добавьте пульт в репозиторий git и обратите внимание на двоеточие перед именем пользователя:

git remote add origin git@github.com:user_name/repo_name.git

И тогда команды git работают нормально, например:

git push origin master
git pull origin 

@HeyWatchЭто в этой теме SO предложило добавить IdentitiesOnly yes чтобы предотвратить поведение SSH по умолчанию при отправке файла идентификации, соответствующего имени файла по умолчанию для каждого протокола. Смотрите эту ветку для получения дополнительной информации и ссылок.

0

Я использую git версии 2.16, и мне не нужен ни один фрагмент скрипта, даже конфигурация или измененные команды.

  • Просто скопировал мой закрытый ключ в .ssh/id_rsa
  • установить разрешения на 600

И Git читает ключ автоматически. Я ничего не спрашиваю, и это не выдает ошибку. Просто отлично работает.

0

Просто используйте команды ssh-agent и ssh-add .

# create a agent
ssh-agent

# add your default key
ssh-add ~/.ssh/id_rsa

# add your second key
ssh-add ~/.ssh/<your key name>

После выполнения вышеуказанных команд вы можете использовать обе клавиши одновременно. Просто введите

git clone git@github.com:<yourname>/<your-repo>.git

подключить свой репозиторий.

Вы должны выполнить вышеуказанную команду после перезагрузки компьютера.

Английский не мой родной язык; пожалуйста, извините за ошибки при печати.

0

Хотя вопрос не требует этого, я этот ответ для всех, кто хочет решить эту проблему специально для .

Гитлаб раствор

Я попытался использовать подход с , но даже в документации git рекомендуется использовать ~/.ssh/config для чего-то большего, чем простой случай. В моем случае я сервер - и я хотел сделать это как определенный пользователь - который, конечно, определяется во время а не именем пользователя git . После внедрения я просто выполняю следующее:

~/myrepo> git mycommit -m "Important Stuff"
~/myrepo> git mypush
[proceed to enter passphrase for private key...]

Настроить

Вспомните расположение вашего /myfolder/.ssh/my_gitlab_id_rsa в моем случае.

Добавьте запись в ~/.ssh/config:

Host gitlab-delegate
    HostName gitlab.mydomain.com
    User git
    IdentityFile /myfolder/.ssh/my_gitlab_id_rsa
    IdentitiesOnly yes

Добавьте в ~/.gitconfig:

mypush = "!f() { \
           path=$(git config --get remote.origin.url | cut -d':' -f2); \
           branch=$(git rev-parse --abbrev-ref HEAD); \
           git remote add gitlab_as_me git@gitlab-delegate:$path && \
           git push gitlab_as_me $branch && \
           git pull origin $branch; \
           git remote remove gitlab_as_me; \
         }; f"

В качестве бонуса я выполняю свои коммиты на этом же хосте как конкретный пользователь с этим :

mycommit = "!f() { \
             git -c "user.name=myname" -c "user.email=myname@mysite.com" commit \"$@\"; \
           }; f"

объяснение

Все вышеперечисленное предполагает, что соответствующий удаленный является origin и соответствующая ветвь в настоящее время извлечена. Для справки я столкнулся с несколькими пунктами, которые необходимо было решить:

  • Решение требует создания нового удаленного gitlab_as_me , и мне не нравилось видеть дополнительный удаленный элемент в моем дереве журналов, поэтому я удаляю его по окончании
  • Для создания удаленного необходимо генерировать URL удаленного на лету - в случае с gitlab это было достигнуто с помощью простого bash
  • Когда вы выполняете push для gitlab_as_me вы должны четко указать, какую ветку вы нажимаете.
  • После выполнения толчка локального указатель origin должен быть "обновлен", чтобы соответствовать gitlab_as_me git pull origin $branch делает это)

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .