【问题标题】:Select private key to use with Git选择与 Git 一起使用的私钥
【发布时间】:2011-10-05 01:02:28
【问题描述】:

我有 2 个 Git 服务器,需要 2 个不同的 SSH 密钥。

git clone user1@server1:blahblahblah 使用 ~/.ssh/id_rsa,但我需要根据我连接的服务器指定要使用的密钥。

执行此工作的 Git 命令行参数是什么? (我正在运行 Linux。)

【问题讨论】:

标签: git ssh


【解决方案1】:

还有另一种可能。那就是设置core.sshCommand,例如

git config --local core.sshCommand "/usr/bin/ssh -i /home/me/.ssh/id_rsa_foo"

这种策略特别有用的一种特殊情况是:当您在 Github 上有多个帐户时,所有帐户 ssh 到 Github 都为 git@github.com,它使用 ssh 键来确定您是哪个 Github 用户.在这种情况下,.ssh/configssh-agent 都不会做你想做的事。

更新 - 在您拥有本地存储库之前,您无法运行上述内容,因此如果您尝试克隆远程存储库,则需要根据 drawbie18 的回答手动指定密钥:

git clone -c core.sshCommand="/usr/bin/ssh -i /home/me/.ssh/id_rsa_foo" git@github.com:me/repo.git

克隆存储库后,您可以使用git config 命令对其进行永久设置。

【讨论】:

  • 这应该是选择的答案。所需的配置在存储库中很好地本地化,需要使用不同的 ssh 密钥来访问不同的 git 服务器。无需修改 ~/.ssh/config(甚至 /etc/hosts,如果 GitHub 上有多个帐户)。
  • 不过有一个问题:在配置它之前你不能克隆一个repo,为了配置它,你需要先克隆它。或者,您可以 git init 一个 repo,在本地配置它以使用正确的 ssh 命令,然后添加一个远程(3 个步骤,而“git clone”只有 1 个步骤)。
  • 要克隆存储库,我将使用@Guss 的解决方案,如下所示,通过设置 GIT_SSH_COMMAND 环境变量。但在正常使用中,我更喜欢我的解决方案,因为它避免了每次启动新 shell 时都必须重新导出该变量。
  • 救命稻草!有很多人展示了如何使用 ./ssh/config 来设置它,并使用 ssh-agent / ssh-add -K for mac。已经使用了一年,但它突然停止在最新补丁的 High Sierra 中工作。当其他一切都失败时,core.sshCommand 起作用了。谢谢!
  • 感谢您提供这个优雅的解决方案。但是我只想准确地说 core.sshCommand 仅适用于git >= 2.10.0
【解决方案2】:

如果您通过 SSH 连接,则密钥将由 SSH 参数控制,而不是 git 参数。

SSH 在~/.ssh/config 文件中查找配置参数。修改该文件并为两个 Git 服务器添加 IdentityFile 条目,如下所示:

Host server1.whatever.com
  IdentityFile /path/to/key_1
Host server2.whatever.com
  IdentityFile /path/to/key_2

This article 有更多细节。

【讨论】:

  • 那没有回答问题。问题是,ssh处理授权的时候,怎么给git这个参数?
  • @Keks:你不能通过 git 命令行传递 ssh 参数。这个答案提供了一种解决方法。还有其他可能的解决方法,例如git.wiki.kernel.org/index.php/…。请注意,该方法也不使用命令行参数来修改 ssh 行为。
  • 确实如此,但是您的原始答案没有回答问题。您也可以使用ssh-agentssh-add,然后只使用git。当 git 通过 ssh 连接时,密钥已经启用。你看,有几种方法,你原来的答案并没有真正的帮助。
  • 这几乎是一个仅链接的答案。您能否在答案中总结文章的相关内容?
  • 这个答案已经过时了。
【解决方案3】:

一般来说,您想为此使用~/.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 作为默认使用的密钥。

【讨论】:

  • 如果您在 GitHub 之类的服务器上拥有多个帐户,并且您希望每个帐户使用不同的私钥,那么这个想法就行不通了。
  • 对于一台服务器上的多个帐户,请参阅此答案stackoverflow.com/questions/3225862/…
【解决方案4】:

在我的场景中,类似于@Richard Smith 场景(其解决方案,顺便说一句,对我不起作用),我需要为不同存储库下的同一服务器使用不同的密钥。

我的解决方法是使用环境变量GIT_SSH_COMMAND 正确设置会话,如下所示:

export GIT_SSH_COMMAND="ssh -o IdentitiesOnly=yes -i ~/.ssh/my-secret-identitiy"

更新

这里要注意的另一件事是,正确设置环境变量可能很麻烦,所以我使用Liquid PromptFish Shell 等提供的命令提示符修改工具连接到 shell 并不断更新环境变量根据当前目录和一些规则。例如,我在 Gitlab 中需要我的个人 SSH 密钥的所有个人项目都在 ~/Documents/Projects/personal 下,因此当 shell 挂钩运行 pwd 并发现当前目录在该路径下时,它会自动将 GIT_SSH_COMMAND 变量设置为需要。

【讨论】:

  • 较旧的 git 客户端(在我的情况下为 1.7.1)调用此环境变量 GIT_SSH。
【解决方案5】:

使用ssh-add path-to-private-key,它开箱即用。

【讨论】:

  • 如果您有两个部署密钥并且它们仅适用于特定存储库,则不会。在这种情况下,它可能会使用错误的密钥并说您无权访问。
  • 我遇到了 cdmckay 说的问题
【解决方案6】:

你可以设置--global或者--local配置,global会更新~/.gitconfig文件,local会更新仓库.git/config中的配置并覆盖全局(~/.gitconfig)配置

git config --local --add core.sshCommand 'ssh -i ~/.ssh/my_key'

【讨论】:

  • 作为一个魅力,这正是我所需要的,一个特定回购的解决方案。
【解决方案7】:

这里的 Windows 用户,我刚刚遇到了这个问题,并且有一个稍微不同的解决方案,然后我在这里读到了。我面临的问题是,我只是想使用特定的私有 ssh 密钥克隆存储库,而不必像在 PowerShell 中工作那样全局配置我的 git config 或添加特定的 git bash 设置。本质上,我只想在我的 .ssh 文件夹中放置一些私钥,并根据需要在特定的存储库中引用它们。

以下命令适用于此:

git clone -c core.sshCommand="ssh -i ~/.ssh/<PRIVATE KEY NAME>" <CLONE URL>

本质上,这是在初始化 git repo 时设置 core.sshCommand 选项,然后再运行克隆。因此,您希望用于此 repo 的特定 ssh 密钥仅为此 repo 设置。这可能不是所有情况下的理想解决方案,但对于我想要的。

【讨论】:

  • 谢谢。我不知道-cgit clone 选项。这比我在克隆时建议的设置环境要好。
  • 这确实应该是公认的答案。它回答了提出的实际问题(以及我也想要答案的问题......)。 PS 它在 linux 上也可以正常工作。
  • (注意其他命令可以在命令前加上-c,例如git push,做git push -c ... etc ... push
【解决方案8】:

另一种选择是编写一个小脚本,让core.sshCommand 更智能一些 - 检查当前工作目录是否配置了特定的 SSH 密钥,如果有,请使用它,否则 - 依赖标准的 SSH 密钥解析。

这是我的第一个版本:

#!/bin/bash
key="$(git config ssh.key)"
if [ -n "$key" ]; then
        ssh -o IdentitiesOnly=yes -i "$key" "$@"
else
        ssh "$@"
fi

然后将其设置为 global git SSH 命令:

chmod 755 ~/.local/bin/git-ssh-command
git config --global core.sshCommand ~/.local/bin/git-ssh-command

~/.local/bin"place user scripts here" on SystemD operating systems 的当前标准)

设置完成后,您可以通过设置配置选项 ssh.key 来配置任何存储库以使用特定的 SSH 密钥:

git config --local ssh.key ~/.ssh/my-non-default-private-key

其他可选技巧

  • 将全局 ssh.key 设置为“默认回退到非默认 SSH 密钥”或其他内容。
  • 当 git 在存储库的根目录中执行 core.sshCommand 时,您的自定义 git-ssh-command 可以查看它并对目录名称进行一些启发。这可以在 else 部分中完成,因此只有在 ssh.key 中没有特定键时才会使用启发式算法。
  • 您可以添加git remote -v 检查以添加基于遥控器的启发式方法,就像在 Eike 的脚本中一样
  • 如果您想查看存储库遥控器,但有多个遥控器需要不同的密钥,您可以在脚本开头添加remote="$1:$(sed "s,.* ,,;s,',,g"&lt;&lt;&lt;"$2")" 以解析正在操作的遥控器 - 并检查($remote 将看起来像git remote -v 输出中的中间列)。

更新:

这是自定义 SSH 命令的一个版本,它查看远程 URL 并执行一些启发式方法 - 在我的例子中,我有几个不同的身份和相同的公共 git 托管服务(一个用于工作,一个用于个人等)和我可以通过查看远程 URL 来选择正确的身份(检查 Gitlab 组或 Github 组织等):

#!/bin/bash
while ! [[ "$1" =~ "git@" ]]; do shift; done # git may send ssh options
if [[ "$2" =~ ^git-lfs-authenticate.* ]]; then # reconstruct url for git-lfs
        remote="$1:$(awk '{print$2}'<<<"$2")"
else # reconstruct url for standard git commands
        remote="$1:$(sed "s,.* ,,;s,',,g"<<<"$2")"
fi
echo "Detected $remote from $@" >&2
key="$(git config ssh.key)"
if [ -n "$key" ]; then # use specified SSH key, if set
        ssh -o IdentitiesOnly=yes -i "$key" "$@"
elif [[ "$remote" == git@gitlab.com:my-company* ]]; then # use company id
        ssh -o IdentitiesOnly=yes -i ~/.ssh/company-id "$@"
elif [[ "$remote" =~ git@bitbucket.org:.*other-org.* ]]; then # bitbucket has weird urls
        ssh -o IdentitiesOnly=yes -i ~/.ssh/custom-org-key "$@"
else # otherwise use whatever the agent has (my personal key)
        ssh "$@"
fi

【讨论】:

    【解决方案9】:

    其他答案启发我编写了一个小脚本,该脚本根据命令行选项或 git remote -v 的值(如果存在)选择 ssh 键。 希望对您有所帮助!

    要真正回答这个问题:使用 gat。

    另见https://bitbucket.org/eikerobert/gat/src/master/

    #!/bin/bash
    
    usegat=false
    
    for VAR in "$@"
    do
        if [ "$VAR" != "${VAR/git@bitbucket.org:myaccount/}" ]; then
            usegat=true
        fi
    done
    
    if [ $usegat=false ]; then
       /usr/bin/git rev-parse --is-inside-work-tree >/dev/null 2>&1
       isinsidegitrepo=$?
        #echo $isinsidegitrepo
       if [ $isinsidegitrepo = 0 ]; then
           remote=`/usr/bin/git remote -v`
           if [ "$remote" != "${remote/git@bitbucket.org:myaccount/}" ]; then
               usegat=true
           fi
       fi
    fi
    
    
    if [ $usegat = true ]; then
        # echo "TRUE"
        /usr/bin/git -c core.sshCommand="/usr/bin/ssh -i /home/myaccount/.ssh/mykey" "$@"
    else
         #echo "FALSE"
        /usr/bin/git "$@"
    fi
    

    【讨论】:

      猜你喜欢
      • 2015-04-11
      • 2023-03-24
      • 2016-08-20
      • 2012-08-06
      • 2013-08-26
      • 1970-01-01
      • 2015-05-23
      • 2014-08-24
      • 2021-09-25
      相关资源
      最近更新 更多