450

我有以下用例:我希望能够推动git@git.company.com:gitolite-admin使用 user 的私钥gitolite-admin,而我想推动git@git.company.com:some_repo使用“我自己的”私钥。AFAIK,我无法使用 解决这个问题~/.ssh/config,因为用户名和服务器名在两种情况下都是相同的。由于我主要使用自己的私钥,因此我在~/.ssh/configfor中定义了该私钥git@git.company.com。有谁知道覆盖用于单个git调用的密钥的方法?

(顺便说一句:gitolite 根据密钥区分谁在进行推送,因此就访问、所有权和审计而言,user@server 字符串对于不同的用户来说是相同的,这不是问题。)

4

17 回答 17

737

即使用户和主机相同,仍然可以区分~/.ssh/config。例如,如果您的配置如下所示:

Host gitolite-as-alice
  HostName git.company.com
  User git
  IdentityFile /home/whoever/.ssh/id_rsa.alice
  IdentitiesOnly yes

Host gitolite-as-bob
  HostName git.company.com
  User git
  IdentityFile /home/whoever/.ssh/id_dsa.bob
  IdentitiesOnly yes

然后,您只需使用gitolite-as-aliceandgitolite-as-bob而不是 URL 中的主机名:

git remote add alice git@gitolite-as-alice:whatever.git
git remote add bob git@gitolite-as-bob:whatever.git

笔记

您希望包含IdentitiesOnly yes阻止使用默认 ID 的选项。否则,如果您还有与默认名称匹配的 id 文件,它们将首先被尝试,因为与其他配置选项(遵守“first in wins”)不同,该IdentityFile选项附加到要尝试的身份列表中。请参阅:https ://serverfault.com/questions/450796/how-could-i-stop-ssh-offering-a-wrong-key/450807#450807

于 2011-10-28T10:03:32.973 回答
104

您可以利用 git 环境变量GIT_SSH_COMMAND。在您的 git 存储库下的终端中运行它:

GIT_SSH_COMMAND='ssh -i ~/.ssh/your_private_key' git submodule update --init

替换~/.ssh/your_private_key为您要使用的 ssh 私钥的路径。并且您可以将后续的 git 命令(在示例中为git submodule update --init)更改为其他命令,例如git pull,git fetch等。

于 2017-05-13T12:58:06.940 回答
60

Mark Longair 提供的上述方法的另一种方法是使用别名,该别名将在任何远程上运行任何git 命令,并带有备用 SSH 密钥。这个想法基本上是在运行 git 命令时切换您的 SSH 身份。

相对于其他答案中的主机别名方法的优势:

  • 即使您无法明确指定,也可以使用任何remotegit 命令或别名。
  • 更容易使用许多存储库,因为您只需要为每台客户端机器设置一次,而不是每台客户端机器上的每个存储库一次。

我使用了一些小脚本和一个 git alias admin。这样我就可以做到,例如:

git admin push 

使用备用(“admin”)SSH 密钥推送到默认远程。push同样,您可以使用带有此别名的任何命令(不仅仅是)。您甚至git admin clone ...可以克隆一个您只能使用“管理员”密钥访问的存储库。

第 1 步:创建备用 SSH 密钥,可选择设置密码,以防您在其他人的计算机上执行此操作。

第 2 步:创建一个名为“ssh-as.sh”的脚本,该脚本运行使用 SSH 的东西,但使用给定的 SSH 密钥而不是默认密钥:

#!/bin/bash
exec ssh ${SSH_KEYFILE+-i "$SSH_KEYFILE"} "$@"

第 3 步:创建一个名为“git-as.sh”的脚本,该脚本使用给定的 SSH 密钥运行 git 命令。

#!/bin/bash
SSH_KEYFILE=$1 GIT_SSH=${BASH_SOURCE%/*}/ssh-as.sh exec git "${@:2}"

第 4 步:添加别名(使用下面的“PATH_TO_SCRIPTS_DIR”适当的名称):

# Run git commands as the SSH identity provided by the keyfile ~/.ssh/admin
git config --global alias.admin \!"PATH_TO_SCRIPTS_DIR/git-as.sh ~/.ssh/admin"

更多详情请访问: http: //noamlewis.wordpress.com/2013/01/24/git-admin-an-alias-for-running-git-commands-as-a-privileged-ssh-identity/

于 2013-01-24T03:12:57.407 回答
52

使用配置您的存储库git config

git config --add --local core.sshCommand 'ssh -i <<<PATH_TO_SSH_KEY>>>'

这仅适用于您的本地存储库

于 2020-06-09T08:39:39.680 回答
41

在阅读其他答案的基础上,我将以下方法拼凑在一起并使用 github 进行了测试,该方法结合了一些技术:

  • 正确的 SSH 配置
  • git URL 重写

这种方法的优点是,一旦设置好,它就不需要任何额外的工作来让它正确 - 例如,您不需要更改远程 URL 或记住以不同的方式克隆东西 - URL 重写使一切正常.

~/.ssh/config

# Personal GitHub
Host github.com
  HostName github.com
  User git
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/github_id_rsa

# Work GitHub
Host github-work
  HostName github.com
  User git
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/work_github_id_rsa

Host *
  IdentitiesOnly yes

~/.gitconfig

[user]
    name = My Name
    email = personal@personal.email

[includeIf "gitdir:~/dev/work/"]
    path = ~/dev/work/.gitconfig

[url "github-work:work-github-org/"]
    insteadOf = git@github.com:work-github-org/

~/dev/work/.gitconfig

[user]
    email = work@work.email

只要您将所有工作存储库保存在 ~/dev/work 和其他地方的个人资料下,git 将在对服务器执行拉取/克隆/推送时使用正确的 SSH 密钥,并且它还会将正确的电子邮件地址附加到所有你的承诺。

参考:

于 2019-10-24T23:12:21.063 回答
16

从 git 2.10 开始,也可以使用 gitconfig sshCommand 设置。文档状态

如果设置了这个变量,当 git fetch 和 git push 需要连接到远程系统时,它们将使用指定的命令而不是 ssh。该命令与 GIT_SSH_COMMAND 环境变量的形式相同,并在设置环境变量时被覆盖。

一个使用示例是:git config core.sshCommand "ssh -i ~/.ssh/[insert_your_keyname]

在某些情况下这不起作用,因为 ssh_config 覆盖了命令,在这种情况下尽量ssh -i ~/.ssh/[insert_your_keyname] -F /dev/null不要使用 ssh_config。

于 2019-06-10T17:55:28.587 回答
15

一个基于 Unix 的系统(Linux、BSD、Mac OS X),默认身份存储在目录$HOME/.ssh中,在 2 个文件中: private key: $HOME/.ssh/id_rsa public key: $HOME/.ssh/id_rsa.pub 当您ssh不使用选项-i时,它使用默认私钥与远程系统进行身份验证。

如果您有另一个要使用的私钥,例如$HOME/.ssh/deploy_key,则必须使用ssh -i ~/.ssh/deploy_key ...

这很烦人。您可以在$HOME/.bash_profile中添加以下行: ssh-add ~/.ssh/deploy_key ssh-add ~/.ssh/id_rsa

因此,每次使用sshorgitscp(基本上ssh也是如此)时,您不必再使用 option-i了。

您可以在文件$HOME/.bash_profile中添加任意数量的键。

于 2016-06-05T03:16:18.723 回答
10

另一种选择是使用ssh-ident 来管理您的 ssh 身份

它会根据您当前的工作目录、ssh 选项等自动加载和使用不同的密钥……这意味着您可以轻松地拥有一个工作/目录和私有/目录,最终透明地使用不同的密钥和身份与 ssh。

于 2014-01-02T02:06:11.037 回答
9

我在 Win7 上使用 Git Bash。以下对我有用。

在 ~/.ssh/config 或 c:/users/[your_user_name]/.ssh/config 创建一个配置文件。在文件中输入:

Host your_host.com
     IdentityFile [absolute_path_to_your_.ssh]\id_rsa

我猜主机必须是一个 URL,而不仅仅是主机的“名称”或参考。例如,

Host github.com
     IdentityFile c:/users/[user_name]/.ssh/id_rsa

路径也可以写成 /c/users/[user_name]/.... 格式

Giordano Scalzo 提供的解决方案也很棒。 https://stackoverflow.com/a/9149518/1738546

于 2014-09-17T23:57:47.027 回答
7

使用的一种可能性~/.ssh/config是使用Match限制而不是Host限制。特别是Match Exec调用 shell 命令来决定是否应用声明。在 bash 中,您可以使用以下命令:

[ git@git.company.com:gitolite-admin = $(git config --get remote.origin.url)'' ]

这使用 bash[命令来验证两个字符串是否相等。在这种情况下,它正在测试字符串是否git@git.company.com:gitolite-admin与从$(git config --get remote.origin.url)''命令获得的输出匹配。

您可以使用任何其他命令来标识 shell 所在的存储库。为此,在我的情况下,将变量定义到您的 shell 中很重要。完整的示例如下:$SHELL/bin/bash~/.ssh/config

Match Exec "[ git@git.company.com:gitolite-admin = $(git config --get remote.origin.url)'' ]"
  IdentityFile ~/.ssh/gitolite-admin
  IdentitiesOnly yes
  ForwardAgent no
  ForwardX11 no
  ForwardX11Trusted no

Match Exec "[ git@git.company.com:some_repo = $(git config --get remote.origin.url)'' ]"
  IdentityFile ~/.ssh/yourOwnPrivateKey
  IdentitiesOnly yes
  ForwardAgent no
  ForwardX11 no
  ForwardX11Trusted no

在此示例中,我假设~/.ssh/yourOwnPrivateKey包含您自己的私钥并且~/.ssh/gitolite-admin包含用户的私钥gitolite-admin。我包含了IdentitiesOnly yes声明,以确保只向 git 服务器提供一个密钥,正如 Mark Longair 所提到的。其他声明只是 git 的标准 ssh 选项。

如果您有多个some_repo要与不同键一起使用的配置,则可以添加此配置。如果您有多个存储库git@git.company.com并且其中大多数都使用~/.ssh/yourOwnPrivateKey它,那么将此密钥作为主机的默认值包含在内更有意义。在这种情况下,~/.ssh/config将是:

Match Exec "[ git@git.company.com:gitolite-admin = $(git config --get remote.origin.url)'' ]"
  IdentityFile ~/.ssh/gitolite-admin
  IdentitiesOnly yes

Host git.company.com
  IdentityFile ~/.ssh/yourOwnPrivateKey
  IdentitiesOnly yes
  ForwardAgent no
  ForwardX11 no
  ForwardX11Trusted no

请注意,顺序很重要,Host git.company.com限制应出现在Match Exec一个或一个之后。

于 2020-05-19T10:04:11.573 回答
6

正如其他人提到的,core.sshCommandconfig 可用于覆盖 SSH 密钥和其他参数。

这是一个示例,其中您有一个名为的备用密钥~/.ssh/workrsa,并希望将其用于克隆下的所有存储库~/work

  1. 在下面创建一个新.gitconfig文件~/work
[core]
  sshCommand = "ssh -i ~/.ssh/workrsa"
  1. 在您的全局 git config~/.gitconfig中,添加:
[includeIf "gitdir:~/work/"]
  path = ~/work/.gitconfig
于 2020-01-30T02:35:04.167 回答
6

要即时使用特定键:

GIT_SSH_COMMAND='ssh -i $HOME/.ssh/id_ed25519 -o IdentitiesOnly=yes -F /dev/null' git push origin c13_training_network

解释:

  • 执行推送之前的本地 ENV var
  • -i指定键
  • -F强制一个空配置,这样你的全局配置就不会覆盖这个临时命令
于 2020-12-08T20:31:48.577 回答
6

如果您已经有默认的 ssh 密钥配置,但想对特定存储库使用不同的配置,那么这应该可以解决问题:

git config core.sshCommand "ssh -i ~/.ssh/github-personal -o IdentitiesOnly=yes -F /dev/null"
于 2021-04-08T20:03:41.177 回答
5

如果在 Windows 上使用 Git 的 ssh 版本,ssh 配置中的身份文件行看起来像

IdentityFile /c/Users/Whoever/.ssh/id_rsa.alice

/c在哪里c:

要检查,在 git 的 bash 中做

cd ~/.ssh
pwd 
于 2014-08-20T06:06:19.213 回答
4

您可能需要删除(或注释掉)默认主机配置 .ssh/配置

于 2017-10-28T08:37:59.353 回答
3

为了让 git 弄清楚,除了更改配置文件之外,它应该使用不同的 SSH 密钥,如此处所述: https ://stackoverflow.com/a/7927828/1306884 您可能还需要清除并重新加载活动的 SSH身份。

在 Mac 上,执行以下操作:

ssh-add -D
ssh-add ~/.ssh/id_rsa_one_that_you_want_to_use_instead

使用这两个命令,并设置 GIT URL 以匹配Hostssh/config 文件中定义的字符串,应该允许您为不同的存储库使用不同的 SSH 密钥。

例如,在克隆存储库时用作Host work.github.comURL 。work.github.comgit@work.github.com:your/repository.git

于 2021-07-07T14:32:14.043 回答
2

您最常在文件配置密钥 ssh 中指定:

# Default GitHub user
Host one
 HostName gitlab.com
 User git
 PreferredAuthentications publickey
 IdentityFile ~/.ssh/key-one
 IdentitiesOnly yes

#two user
Host two
 HostName gitlab.com
 User git
 PreferredAuthentications publickey
 IdentityFile ~/.ssh/key-two
 IdentitiesOnly yes
于 2019-01-26T05:40:06.327 回答