ssh具有-i选项,用于告诉您在进行身份验证时使用哪个私钥文件:或读取DSA身份验证。
协议版本1的默认值为-i identity_file
协议版本2的默认值为~/.ssh/identity~/.ssh/id_rsa
身份文件也可以在每个主机的基础上指定
。可能有多个~/.ssh/id_dsa选项
(以及配置文件中指定的多个标识)。


是否有类似的方法告诉-i在服务器上使用哪个私钥文件系统在git目录中具有多个私钥?

评论

在StackOverflow中也可以看到此问题。

也相关的serverfault.com/questions/194567/…

#1 楼

~/.ssh/config中,添加:
Host github.com
 HostName github.com
 IdentityFile ~/.ssh/id_rsa_github

如果配置文件是新的,则可能需要执行chmod 600 ~/.ssh/config
现在您可以执行git clone git@github.com:{ORG_NAME}/{REPO_NAME}.git

其中{ORG_NAME}是您的GitHub用户帐户(或组织帐户)的GitHub URI名称。

请注意,在:后面有一个冒号github.com而不是斜杠/-因为这不是URI。


{REPO_NAME}是您的GitHub存储库的URI名称。
例如,对于Linux内核,它是git clone git@github.com:torvalds/linux.git)。

注意:在Linux和macOS上,请验证您的权限IdentityFile是400。SSH将以一种不太明确的方式拒绝太易读的SSH密钥。看起来就像是凭证拒绝。在这种情况下,解决方案是:
chmod 400 ~/.ssh/id_rsa_github


评论


如果您需要使用不同的密钥连接到同一主机怎么办?

–华伦丁·克林汉默(Valentin Klinghammer)
2012年11月30日在11:24

@Quelltextfabrik-您可以使用其他主机添加另一部分:nerderati.com/2011/03/…

– Ben Challenor
2012年12月4日14:17

如果配置文件是新的,请不要忘记执行chmod 600〜/ .ssh / config

– elysch
16 Mar 15 '16 at 23:02

@ValentinKlinghammer @Flimm的答案提供了此问题的解决方案。它是使用core.sshCommand git配置的。 superuser.com/a/912281/162466

–VasyaNovikov
17年12月28日在20:47

这迫使git在整个域中使用特定的密钥,这通常是行不通的。例如,如果某人拥有一个个人github帐户和一个工作帐户,则此配置将破坏其中一个。

–塞林
19年8月22日在20:09

#2 楼

环境变量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


评论


我必须将shell变量导出到环境变量中才能完成此工作,即,导出GIT_SSH_COMMAND =“ ssh -i〜/ .ssh / id_rsa_example”,然后是git clone示例

–阿卜杜勒(Abdull)
2015年1月1日于13:46



@Abdull在Bash中,在与命令相同的行上进行分配,仅导出该命令的环境变量。尝试一下:example = hello / usr / bin / env | grep示例。

– Flimm
16年1月8日,9:50

事情变得更好:从Git 2.10开始,您可以将命令存储在Git配置中:stackoverflow.com/a/38474220/520162

–eckes
16-10-21在7:57

@Noitidart / dev / null在类似UNIX的操作系统中只是一个有效的文件名,在Windows上不起作用。

– Flimm
17年7月7日在8:19

对我来说,直到我使用IdentitiesOnly,GIT_SSH_COMMAND才起作用,例如以下命令:GIT_SSH_COMMAND =“ ssh -i〜/ .ssh / mysubdir / id_rsa -o'IdentitiesOnly yes''” git push。

–泰勒·科利尔(Tyler Collier)
18-10-7在7:13

#3 楼

没有直接方法告诉git使用哪个私钥,因为它依赖ssh进行存储库身份验证。但是,仍有一些方法可以实现您的目标:

选项1:ssh-agent


您可以使用ssh-agent临时授权私钥。

例如:

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


选项2:GIT_SSH_COMMAND


通过使用GIT_SSH_COMMAND传递ssh参数环境变量
(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


通过使用GIT_SSH环境变量指定备用ssh二进制文件传递ssh参数。 br />
例如:

$ 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


注意:以上几行是shell(终端)命令行,应粘贴到终端中。他们将创建一个名为ssh的文件,使其可执行并(间接)执行。

注意:GIT_SSH自v0.99.4(2005)起可用。

选项4 :~/.ssh/config


使用其他答案中建议的~/.ssh/config文件来指定私钥的位置,例如

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


评论


//,但是,如果转发您在ssh-agent中的身份,如该问题那样呢? superuser.com/questions/971732/…

– Nathan Basanese
2015年9月11日18:06

我允许我重新格式化此帖子:IMO,这是迄今为止最全面的答案。在其原始设计中,快速扫描显示了该帖子,其中描述了该问题的单个复杂解决方案,因此我错过了。

–阿尔贝托
16年1月21日在10:01

$ ssh-agent sh -c'ssh-add〜/ .ssh / id_rsa; git fetch user @ host'帮了我大忙。荣誉

–丹尼尔·德赫斯特(Daniel Dewhurst)
17年9月11日在15:24

我不得不使用〜/ .ssh / config方法,env vars对我不起作用...

– Greg Dubicki
17年9月22日在7:53

GIT_SSH自v0.99.4(2005年8月)开始可用,因此基本上是因为Git存在(2005年4月)。

–多米尼克
17年11月17日在8:10

#4 楼

~/.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  


评论


这是我一直在寻找的答案,因为我有用于家庭和工作的单独的GitHub帐户。我只需要设置Host work.github.com HostName github.com IdentityFile〜/ .ssh / work,然后在每次克隆工作存储库时都将“ github.com”替换为“ work.github.com”。它仍然连接到“ github.com”,但是使用非默认密钥对。

– Mikkel
16年5月25日在17:06



详细信息的URL(“ itblog.study.land / ...”)不再起作用:(

–卡尔·斯莫特里兹(Carl Smotricz)
17年9月15日在8:10

@CarlSmotricz,原来的一个移到了这里:medium.com/@thucnc/…

– thucnguyen
18年11月27日在7:13

最后!!!该答案实际上显示了如何利用〜/ .ssh / config文件中的内容。其他所有答案都错过了添加原始地址时如何设置主机的信息,原始地址会自动允许git使用正确的密钥文件。谢谢!!

– BrianVPS
18/12/4在15:17

很好,那是我一直在寻找的东西:)

–卢卡斯·德阿维拉(Lucas D'Avila)
19年4月4日在18:19

#5 楼

编写一个使用所需参数调用ssh的脚本,然后将该脚本的文件名放入$GIT_SSH中。或者只是将您的配置放在~/.ssh/config中。

评论


关于如何执行此操作的另一种解释。

– Sithsu
2014年5月12日19:44



〜/ .ssh / config是要走的路。

– hek2mgl
2015年5月8日13:56

我在机器(A)上工作,我从该机器git push到仅接受ssh密钥身份验证的服务器(B)。当我直接在那台计算机上工作时,虽然我在(A)上的〜/ .ssh / config设置工作正常,但是当我从其他位置(C)登录时却不能。使用$ GIT_SSH和脚本可以解决此问题。谢谢!

–bsumirak
15年12月3日在17:28

#6 楼

如果您不想每次运行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代理-如果您想要无人值守的克隆/推送/拉取(例如在cron中),则非常有用
绝对不需要外部工具


评论


这个答案正是我要让Chef的git资源使用特定于存储库的部署密钥从私有Github存储库克隆/获取所需的。与基于环境/基于脚本的方法相比,此方法的另一个优点是,由于密钥路径是在工作存储库的配置中编码的,因此它将在初始克隆和后续提取/推送中使用相同的密钥。

–亚当·佛朗哥(Adam Franco)
15年11月19日在16:20

哇!这太好了,对此一无所知。感谢您的回答,在木偶环境中也非常有帮助,可以避免管理.ssh / config等的额外麻烦。+1!

– gf_
16 Jun 10'在18:36



此解决方案不能与--recursive标志一起使用。子模块未使用指定的密钥获取,因此如果它们需要身份验证,则会失败。

–丹尼尔(Daniele Testa)
16年12月21日在16:05

每个子模块是一个完全不同的存储库,具有自己的一组遥控器。为了您的方便,它们由Git粘合在一起,但是子模块的远程绝不与父存储库中的远程绑定。恐怕您必须在每个子模块中使用ext传输设置远程,才能在父级中递归工作。

– Flaviovs
16/12/22在19:10



如果遇到以下致命错误:不允许传输“ ext”,则必须通过导出GIT_ALLOW_PROTOCOL = ext将ext协议列入白名单。基本上,git-remote-ext远程帮助器(支持“ ext :: ssh example.com%S foo / repo” URL)允许任意命令执行。通常,这从来都不是问题,因为用户始终会看到并信任他们传递给git的URL。但是,git子模块通过.gitmodules文件允许攻击者请求客户端获取任意git URL。 hackerone.com/reports/104465

– Gomino
18年5月13日在17:21



#7 楼

在与$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


,所有脚本都将正常工作。

评论


谢谢。请注意:直通参数使用“ $ @”而不是$ *,因为当参数包含空格时,前者的行为正确。

– Piotr Findeisen
16-3-31在7:39

@PiotrFindeisen感谢您的来信。但是,我并不完全理解它-在zsh中,它可以帮助我将字符串与空格保持在一块,但在bash中却不能。您能告诉我更多信息或指出一些解释吗?我不想盲目添加一些修改。

– Jan Vlcinsky
16 Mar 31 '16 at 10:33

您应该删除答案的前半部分。没有人对不起作用的解决方案感兴趣,浪费了阅读内容,混淆了底部的正确答案,效果很好。

–塞林
18年8月3日在16:47



@Cerin如果您的意思是删除“避免错误”,我将其保留在那里。它有共同的陷阱要避免,而且很短。我敢肯定,有人会尝试通过将所有事物都提供给变量来优化解决方案(这发生在我身上),所以我试图缩短成功之路。

– Jan Vlcinsky
18年8月4日在20:14

#8 楼

我有一个需要单独的github帐户的客户端。所以我只需要为此项目使用一个单独的密钥。

我的解决方案是将其添加到我的.zshrc / .bashrc中:

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


每当我要在该项目中使用git时,我都会用git替换“ infogit”:

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


对我来说,更容易记住。

#9 楼

因此,我将GIT_SSH env变量设置为$HOME/bin/git-ssh

为了支持让我的repo配置决定要使用的ssh身份,我的~/bin/git-ssh文件是这样的:

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


然后我有一个全局git配置设置:

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


在任何git存储库中,我都可以设置本地ssh.identity git配置值:

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


Voila!

如果每个身份都可以有不同的电子邮件地址,它将变得更加简单,因为您可以在以下位置命名密钥您的电子邮件地址,然后让git config的user.email在~/bin/git-ssh中驱动密钥选择,如下所示:

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


#10 楼

您可以只使用ssh-ident而不是创建自己的包装器。

您可以在以下位置阅读更多信息:
https://github.com/ccontavalli/ssh-ident

它会在需要时按需加载ssh密钥,一次,甚至具有多个登录会话,xterm或NFS共享房屋。

通过一个很小的配置文件,它可以自动加载不同的密钥并保留它们根据您的需要分为不同的代理(用于代理转发)。

#11 楼

如果需要使用不同的密钥连接到同一主机,则可以通过以下方法实现:


使用不同的主机但主机名相同的~/.ssh/config进行配置。
使用合适的主机。

示例:

~/.ssh/config

Host work
 HostName bitbucket.org
 IdentityFile ~/.ssh/id_rsa_work
 User git

Host personal
 HostName bitbucket.org
 IdentityFile ~/.ssh/id_rsa_personal
 User git


然后克隆您的存储库,例如:

git clone git@bitbucket.org:username/my-work-project.git
git clone git@bitbucket.org:username/my-personal-project.git


你必须做

git clone git@work:username/my-work-project.git
git clone git@personal:username/my-personal-project.git


#12 楼

我的解决方案是:

创建脚本:

#!/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=]


别忘了多余的圆点!!这使脚本设置了环境变量! --key和--port是可选的。

#13 楼

通常,您要为此使用~/.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设置为使用。

#14 楼

我在@shellholic和这个SO线程上构建了一些柚木。我以GitHub为例,假设您在~/.ssh/github中有一​​个私钥(否则,请参见此SO线程),并且已将公钥添加到GitHub个人资料中(否则请参见GitHub的帮助)。

如果需要,请在~/.ssh/config处创建一个新的SSH配置文件,并将权限更改为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 


@HeyWatchThis在此SO线程上建议添加IdentitiesOnly yes以防止SSH默认行为,即发送与每个协议的默认文件名匹配的身份文件。有关更多信息和参考,请参见该线程。

评论


这是我的错误:“如果您已经进行了远程设置...”。非常感谢!!!

–艾伦·安德拉德(Allan Andrade)
18-10-4在17:43

常见错误-这就是答案

–古达
19年5月16日在21:07

#15 楼

只需使用ssh-agentssh-add命令。

# create an 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


克隆存储库。

重新启动计算机后,需要执行上述命令。

评论


请说明该过程,包括如何创建代理

– Srikrushna
19年4月6日在20:20

听起来很聪明,但考虑到所有其他答案有多笨拙,可能听起来有点不错。我无法使它正常工作。

–泽斯
8月15日9:48

@Zeth创建ssh代理时,您可能会遇到问题。如果使用MacOS,则只需执行ssh-agent。如果您使用的是Linux,建议您阅读这篇文章wiki.archlinux.org/index.php/SSH_keys#ssh-agent

–罗金m
12月26日17:53

#16 楼

    # start :: how-to use different ssh identity files

    # create the company identity file
    ssh-keygen -t rsa -b 4096 -C "first.last@corp.com"
    # save private key to ~/.ssh/id_rsa.corp, 
    cat ~/.ssh/id_rsa.corp.pub # copy paste this string into your corp web ui security ssh keys

    # create your private identify file
    ssh-keygen -t rsa -b 4096 -C "me@gmail.com"
    # save private key to ~/.ssh/id_rsa.me, note the public key ~/.ssh/id_rsa.me.pub
    cat ~/.ssh/id_rsa.me.pub # copy paste this one into your githubs, private keys

    # clone company internal repo as follows
    GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa.corp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" \
    git clone git@git.in.corp.com:corp/project.git

    export git_msg="my commit msg with my corporate identity, explicitly provide author"
    git add --all ; git commit -m "$git_msg" --author "MeFirst MeLast <first.last@corp.com>"
    GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa.corp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" \
    git push 
    # and verify 
    clear ; git log --pretty --format='%h %ae %<(15)%an ::: %s

    # clone public repo as follows
    GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa.corp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" \
    git clone git@github.com:acoolprojectowner/coolproject.git

    export git_msg="my commit msg with my personal identity, again author "
    git add --all ; git commit -m "$git_msg" --author "MeFirst MeLast <first.last@gmail.com>"
    GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa.me -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" \
    git push ; 
    # and verify 
    clear ; git log --pretty --format='%h %ae %<(15)%an ::: %s

    # stop :: how-to use different ssh identity files


#17 楼

我使用的是git版本2.16,不需要脚本,甚至不需要配置或修改的命令。


只需将我的私钥复制到.ssh / id_rsa
将权限设置为600

,git会自动读取密钥。我什么都没问,也没有抛出错误。一切正常。

评论


您是否注意到这个问题与“〜/ .ssh目录中具有多个私钥的系统”有关?

–斯科特
18年6月6日在5:16

#18 楼

虽然这个问题并没有要求,但我将这个答案提供给其他想专门解决gitlab问题的人。

gitlab解决方案

我尝试使用环境变量方法,但是即使git文档也建议使用~/.ssh/config来实现比简单情况更多的操作。就我而言,我正在推送到gitlab服务器-我想以特定用户的身份进行操作-这当然是由身份验证期间的私钥而不是用户名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中添加git别名:

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"


作为奖励,我使用git-alias在与特定用户相同的主机上执行提交:

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


说明

以上所有假设相关的远程控制器是origin,并且相关的分支当前已签出。作为参考,我遇到了一些需要解决的问题:


该解决方案需要创建一个新的远程gitlab_as_me,我不希望在日志树中看到多余的远程信息因此,我在完成后将其删除
为了创建遥控器,需要动态生成遥控器的url-对于gitlab,这是通过简单的bash cut实现的

执行对gitlab_as_me的推送时,您需要具体说明要推送的分支
执行推送后,需要对本地origin指针进行“更新”以匹配gitlab_as_megit pull origin $branch这样做)


#19 楼


当您有多个git帐户并且想要不同的ssh密钥时,

您必须遵循相同的步骤来生成ssh密钥,但请确保



ssh-keygen -t ed25519 -C "your-email-id@gmail.com" 


输入要保存的路径(例如:my-pc / Desktop / .ssh / ed25519)

将公钥添加到您的gitlab(如何在gitlab中添加ssh密钥)


您必须使用以下命令重新设置ssh身份



ssh-add ~/my-pc/Desktop/.ssh/ed25519


评论


(1)您在引用某人或某物吗?如果是这样,请确定来源。如果没有,请不要使用引号格式。 (2)什么是“ ed25519”? …………………………………………………………请不要回应任何评论;编辑您的答案,使其更清晰,更完整。

–斯科特
19年4月7日,0:35