ChatGPT解决这个技术问题 Extra ChatGPT

为给定域的 git push 指定 SSH 密钥

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

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


C
Community

即使用户和主机相同,在~/.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-alicegitolite-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 文件,它们将首先被尝试,因为与其他配置选项(遵守“先入先出”)不同,IdentityFile 选项追加到身份尝试。请参阅:https://serverfault.com/questions/450796/how-could-i-stop-ssh-offering-a-wrong-key/450807#450807


太好了,谢谢。我不明白您可以在 ~/.ssh/config 中为主机规范自由选择“别名”
也感谢这个答案!对我来说,一个问题是 IdentityFile 需要是一个完整的路径(我只将 id_rsa.rick 作为 IdentityFile 的参数,但失败了)。有关 IdentityFile 的其他语法,请参见 ssh_config(5) 手册页。
非常感谢您提供清晰且非常有帮助的答案。我曾试图让它工作一段时间,但之前放弃了假设同一个用户必须使用相同的 id_rsa 私钥文件。
遥控器中的 git@ 部分不是必需的,因为它在配置的 User 行中给出。
我一直在为这个解决方案苦苦挣扎,直到我在主机的 IdentityFile 行之后立即添加了另一行包含 IdentitiesOnly yes 的行。似乎它传递了多个身份,其中一个被阻止访问主机。
H
Hustlion

您可以使用 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 pullgit fetch 等其他命令。


完整文档位于 git-scm.com/docs/git#git-codeGITSSHcode;不过,它需要一个 recentish Git (>=2.3.*)。
感谢您提供了一个简单的解决方案,除了设置一个环境变量之外不需要任何东西。
请注意,您的 ~/.ssh/id_rsa(或任何您的默认密钥)将优先于您通过 -i 传入的密钥。所以你真的想使用 GIT_SSH_COMMAND='ssh -i ~/.ssh/your_private_key -o IdentitiesOnly=yes' 让它忽略其他键
如何更新 git push?我在文档中找不到
我还需要强制一个空配置,因为我的主要配置是覆盖 -i 标志 -F /dev/null
e
episage

使用 git config 配置您的存储库

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

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


我喜欢这种方式,因为它在每个回购的基础上工作并且它是持久的
是的,这是完美的答案。干净,简单,简洁。非常感谢!
最佳答案,简单且“有效”
你拯救了我的一天。超级感谢!
C
Community

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

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

即使您无法明确指定远程,也可以使用任何 git 命令或别名。

更容易使用许多存储库,因为您只需要为每台客户端机器设置一次,而不是每台客户端机器上的每个存储库一次。

我使用了一些小脚本和一个 git 别名 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/


非常好的答案。不要忘记在 $@ 周围添加双引号 -> "$@" 为了安全。
@sinelaw 这仍然有效吗?我一直收到 Permission denied 错误
k
karlos

在阅读其他答案的基础上,我将以下方法拼凑在一起并使用 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 密钥,并且它还会将正确的电子邮件地址附加到所有你的承诺。

参考:

1

2


这如何与克隆一起工作? includeIf 应该只在我认为存在 .git 目录的情况下才有效?
等等,我明白了,是 URL 重写来解决这个问题。这个答案非常有用!
工作,但必须删除 UseKeychain 行。欲了解更多信息:stackoverflow.com/a/47455373/2037998
f
firfin

从 git 2.10 开始,也可以使用 gitconfig sshCommand 设置。 Docs state

如果设置了这个变量,当 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。


C
Châu Hồng Lĩnh

一个基于 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

因此,每次您使用 sshgitscp(基本上也是 ssh)时,您不必再使用选项 -i

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


r
rabexc

另一种选择是使用 ssh-ident, to manage your ssh identities

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


C
Community

我在 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


L
LuisR

使用 ~/.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 一个或一个之后。


谢谢 - 这实际上解决了在 VSCode 上一直困扰我的问题 - Open On Github 扩展将使用 Host gitolite-as-alice 中的 Host 值(忽略 HostName),但这种方法避免了这个问题!请注意,您还可以使用通配符来匹配:Match Exec "[[ $(git config --get remote.origin.url)'' == 'git@github.com:YourOrganization'* ]]"
谢谢,我使用了第二种情况并与 Match Exec "[[ $(git config --get remote.origin.url)'' == 'git@github.com:YourOrganization'* ]]" 合作
出于兴趣(我还没有尝试过这种方法):为什么需要这些单引号?如果这是简单的 Bash,那么条件可以像这样简单:Match Exec "[[ $(git config --get remote.origin.url) == git@github.com:YourOrganization/* ]]"(注意组织名称后面的斜杠,因此它不会与 YourOrganizationAnother 重叠)
L
Lukas Lukac

要即时使用特定键:

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 强制一个空配置,所以你的全局配置不会覆盖这个临时命令


M
Mansour

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

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

在 ~/work 下创建一个新的 .gitconfig 文件:

[core]
  sshCommand = "ssh -i ~/.ssh/workrsa"

在你的全局 git config ~/.gitconfig 中,添加:

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

o
omerkarabacak

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

git config core.sshCommand "ssh -i ~/.ssh/github-personal -o IdentitiesOnly=yes -F /dev/null"

A
Artjom B.

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

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

其中 /c 代表 c:

要检查,在 git 的 bash 中做

cd ~/.ssh
pwd 

V
ViliusK

https://i.stack.imgur.com/hb86h.png


M
Michael

为了让 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 以匹配 ssh/config 文件的 Host 中定义的字符串,应该允许您为不同的存储库使用不同的 SSH 密钥。

例如,对于 Host work.github.com,在克隆您的存储库 git@work.github.com:your/repository.git 时使用 work.github.com 作为 URL。


D
Diego Santa Cruz Mendezú

您最常在文件配置密钥 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

A
Amr Awad

注意:有一种方法可以将 previous answer 中建议的 git 配置应用于目录,而不仅仅是在 repo 级别。

在我的例子中,所有项目都在 ~/work/ 目录下,所以我更新了我的 gitconfig 如下:

# ~/.gitconfig
...

[includeIf "gitdir:~/work/**"]
  path = "~/work/.gitconfig"
# ~/work/.gitconfig
[user]
  email = amr@work.com
  name = Amr Awad
  sshCommand = ssh -i ~/.ssh/work

现在 ~/work/ 目录中的所有存储库都使用工作密钥 ~/.ssh/work,而无需单独配置每个存储库。


J
Juan Torres

这是简单的方法:

- 从您的本地根 git 文件夹。

- 检查本地存储库的当前身份验证方法 HTTPS 或 SSH 类型。

   git remote -v

 Example using HTTPS:
 origin  https://github.com/juantorres9/SQLite_crash_cours.git (fetch)
 origin  https://github.com/juantorres9/SQLite_crash_cours.git (push)
 Example using SSH:
 origin  git@github.com:juantorres9/SQLite_crash_cours.git (fetch)
 origin  git@github.com:juantorres9/SQLite_crash_cours.git (push)

- 设置您选择的身份验证方法,以防尚未设置。

 For setting SSH
 git remote set-url origin git@github.com:USERNAME/REPOSITORY.git
 For setting HTTPS
 git remote set-url origin https://github.com/USERNAME/REPOSITORY.git

- 再次检查,以防你想仔细检查

 git remote -v

-您现在可以使用配置的方法使用 git push:fetch。

git push origin master

注意 最后但同样重要的是,请查看更新的官方文档https://docs.github.com/en/get-started/getting-started-with-git/managing-remote-repositories