选择要与 Git 一起使用的私钥

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

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

这个工作是用什么 Git 命令行参数完成的? (我正在运行 Linux。)

112621 次浏览

如果您通过 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

本文 有更多细节。

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

通常,您需要使用 ~/.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作为默认键来使用。

There is another possibility. That's to set core.sshCommand, e.g.

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都不会做你想要的。

更新 & mash; 在拥有本地存储库之前,不能运行上面的代码,所以如果您试图克隆一个远程存储库,您需要根据 drewbie18的回答手动指定密钥:

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

一旦克隆了存储库,就可以使用 git config命令永久地设置它。

[更新] : 请参阅 我的另一个答案,了解基于配置的方法,以及您可以使用的现成脚本

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

对我来说,解决方法是使用环境变量 abc 0正确设置会话,如下所示:

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

更新 :

另一件需要注意的事情是,正确设置环境变量可能会很麻烦,所以我使用了命令提示符修改工具,比如 液体提示或者 鱼壳,来连接到 shell 中,并根据工作目录和一些规则不断更新环境变量。例如,我所有的个人项目,需要我的个人与 Gitlab 的 SSH 密钥是在 ~/Documents/Projects/personal下,所以当 shell 钩子运行的 pwd,发现工作目录是在该路径下,它会自动设置的 GIT_SSH_COMMAND变量的需要。

您可以设置—— global 或—— local 配置,global 将更新 ~/.gitconfig文件,local 将更新存储库 .git/config中的配置并覆盖 global (~/。Gitconfig)配置

Git config —— local —— add core.sshCommand’s sh-i git config —— local ——添加 core.sshCommand 的 ssh-i ~/. ssh/my _ key’

Windows 用户在这里,我只是遇到了这个问题,有一个稍微不同的解决方案,然后我在这里读到目前为止。我遇到的问题是,我只想使用特定的私有 ssh 密钥克隆一个 repo,而不需要像在 PowerShell 中那样全局配置我的 git 配置或添加特定的 git bash 设置。本质上我只是想有一些私人钥匙,坐在我的。Ssh 文件夹,我参考他们在特定的回购要求。

下面的命令适用于这种情况:

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

本质上,这样做是在 git repo 初始化时,在运行克隆之前设置 core.sshCommand 选项。因此,您希望用于此回购的特定 ssh 键仅设置为此回购。这可能不是一个理想的解决方案,为所有情况下,但我想它是。

其他答案启发我编写一个小脚本,根据命令行选项或(如果存在) 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

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

这是我的第一个版本:

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

然后将其设置为 全球性的 git SSH 命令:

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

(~/.local/bin是目前 在 SystemD 操作系统上“将用户脚本放在这里”的标准)

After you set this up, you can configure any repository to use a specific SSH key by setting the configuration option ssh.key:

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

其他可供选择的技巧

  • 将全局 ssh.key设置为具有“默认回退到非默认 SSH 密钥”或类似设置。
  • As git executes core.sshCommand in the root directory of the repository, your custom git-ssh-command can look at that and have some heuristics about directory names. This can be done in the else section so heuristics only kick in if there is no specific key in ssh.key.
  • 您可以添加 git remote -v检查,以添加基于远程启发,如在艾克的脚本
  • 如果您想查看存储库远程,但是有多个远程需要不同的键,那么可以在脚本的开头添加 remote="$1:$(sed "s,.* ,,;s,',,g"<<<"$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