我到现在还记得第一次在终端里敲下git push origin main,屏幕转了几圈之后弹出一行红色报错时的茫然:Permission denied (publickey)。那会儿我刚接触 Git 没多久,连 SSH 是什么都说不清楚,以为自己把仓库地址抄错了,反复把git@github.com:xxx/xxx.git这段复制粘贴了五六遍。直到后来把 SSH 协议和密钥配置的来龙去脉弄明白,才发现这行报错背后藏着一整套完整的认证逻辑。
今天想把这块内容从零讲清楚。这篇博文不是什么高深理论,就是围绕"Git 仓库连接失败"这个新手程序员几乎都会撞上的问题,把 SSH 协议在干什么、密钥是怎么生成和部署的、常见报错为什么会出现、以及怎么一步步排查修复,全部说透。适合刚开始用 Git 和 GitHub/Gitee/GitLab 的人,也适合那些已经能连上但完全靠复制粘贴命令、出了问题就懵的开发者。看完你会发现自己也能独立处理 SSH 连接问题。
1. 连接失败背后的三个疑问:SSH 到底在验证什么
1.1 一条 git clone 命令背后发生了什么
很多人对 SSH 的认知停留在"这是一种安全协议"这句话上,但实际用 Git 时,一条git clone git@github.com:owner/repo.git命令输入进去,客户端和服务器之间其实发生了一连串的交换过程。
我可以把简化后的流程先摆出来:
- 你的 Git 客户端通过 22 号端口向服务器发起 TCP 连接。
- 服务器返回自己的主机公钥(Host Key),用于确认你连接的是真服务器,防止中间人冒充。
- 双方协商加密算法和会话密钥,建立加密通道。
- 服务器开始验证"你是谁"。如果配置了密钥认证,它会要求客户端出示私钥签名;如果走密码认证,则要求输入密码。
- 验证通过后,SSH 会话建立,Git 在这个加密通道里完成仓库数据的传输。
大多数新手遇到Permission denied (publickey),就是卡在了第 4 步。服务器说"请你证明你是这个仓库的合法访问者",而你的客户端拿不出匹配的密钥,或者根本没去尝试密钥认证,于是连接被拒绝。
这里经常被忽略的事实是:SSH 并不是只有密钥这一种认证方式。它还可以用密码认证。那为什么用 Git 时几乎都推荐配置密钥?因为 Git 命令是自动化、脚本化的操作场景,每次git push都弹一个密码输入框会非常打断节奏,而且密码认证意味着密码要经过 SSH 传输通道,只要密码存在单一性风险,泄露一次就等于账号不设防。密钥认证则不同,它靠的是一对公私钥进行非对称加密验证,后面会详细讲。
1.2 为什么连接失败总是出现在"配置密钥"这个环节
Git 仓库连接失败的问题,十有八九最终都指向同一个源头:本地根本没有生成过 SSH 密钥对,或者生成了但公钥没有放到远端平台上。
在 GitHub、Gitee、GitLab 这类平台上,SSH 公钥是绑定到账号下的。你用 Git 客户端发起操作时,服务器会拿着你账号下存的所有公钥去验证你这次连接出示的私钥是否匹配其中一把。如果匹配,就允许访问该账号有权访问的所有仓库。
也就是说,整个过程被拆成了两段独立的配置:
- 本地要拥有一对密钥(私钥 + 公钥)。
- 公钥要提前部署到远端平台的账号设置里。
很多新手只做了其中一段。比如有的人在 Windows 上装完 Git for Windows 就开始用,从来没跑过ssh-keygen;也有人生成过密钥,但把公钥内容复制错了,复制成了私钥,或者复制的时候漏掉了一大段字符。这些都会导致同一行Permission denied (publickey)。
另外还有一个反直觉的点:SSH 密钥和 Git 账号的邮箱、用户名并没有天然的绑定关系。你在本地配置的git config --global user.email只是写进提交记录里的信息,与 SSH 认证使用的是两套体系。也就是说,就算你邮箱填错了,SSH 照样能连上仓库;反过来,SSH 密钥不对,邮箱填得再正确也无济于事。这两件事经常被混为一谈,排查问题时尤其要分开看。
1.3 报错信息里的关键词比你想的有用
新手看到英文报错容易慌,但其实 SSH 的报错信息相当直白。我把常见的关键词和它们对应的含义整理成了一张表:
| 报错关键词 | 实际含义 | 优先排查方向 |
|---|---|---|
Permission denied (publickey) | 公钥认证失败,服务器不认你这次连接 | 本地密钥是否存在、公钥是否已添加、ssh-agent 是否加载了私钥 |
Host key verification failed | 服务器主机公钥没有在 known_hosts 里,或与之前不一致 | 确认不是中间人后,手动清除 known_hosts 中的对应条目 |
Connection timed out | 22 端口连接超时 | 防火墙、企业网络策略、服务器端口是否开放 |
Connection refused | 目标端口没有服务监听 | 服务器 SSH 服务是否启动、端口是否写错 |
Bad owner or permissions on config | SSH config 文件权限不符合要求 | 修正文件权限,Windows 上用 icacls 处理 |
很多人拿到报错只会搜整句,其实先看关键词能节省大量时间。比如Connection timed out和Permission denied完全是两类问题,前者是网络层不通,后者是认证层被拒。后面我会单独开一章讲每条报错的完整排查链路,这里先记住一个原则:报错本身就是最好的线索。
2. 从密码到密钥:SSH 协议为什么选择非对称加密
2.1 对称加密、公钥和私钥,一个生活化的理解方式
要理解 SSH 密钥认证,得先理解非对称加密。
先说对称加密。假设你要给朋友寄一个上锁的盒子,盒子靠同一把钥匙开锁。可是钥匙怎么安全地交到朋友手里?你要么当面给他,要么冒着钥匙被截获的风险邮寄。网络传输中面临的就是这个问题,双方要用同一个"秘密"加密和解密,但建立通信的那一刻,这个秘密还不能通过网络明文传输。
非对称加密的思路完全不同。它生成一对钥匙:一把是公钥,可以公开给任何人;一把是私钥,必须自己保管。公钥加密的数据,只有配对的私钥能解开;反过来,私钥签名或加密的数据,只有配对的公钥能验证。类比来说,公钥像是全世界都知道的锁,任何人都可以把锁锁上,但只有持有私钥这把唯一钥匙的人能打开。
放在 SSH 认证场景里是这样的:你的公钥提前放到了服务器上,服务器想要确认"你是私钥的持有者"时,只需要发一个挑战给你,你能用私钥完成签名并返回,服务器用公钥验证签名通过,就确认了你的身份。整个过程中,私钥从来没有离开过你的电脑,也就不会因为网络传输而泄露。
这个过程很像酒店门卡:前台(服务器)记录了你对应的房卡编号(公钥),你刷卡开门时必须出示房卡,门锁验证编号匹配才放行。房卡就是你的私钥,不需要交给任何人。
2.2 为什么 SSH 推荐密钥而非密码
我见过有人问:SSH 不是说支持密码登录吗,那把密码配到 Git 里用不就得了,为什么还要鼓捣密钥?
原因有几点,都很实际:
防暴力破解。Git 仓库服务器全天候暴露在公网上,密码登录对服务器端来说意味着它必须维护一个可被尝试的密码验证入口。密钥认证在服务端是"只认锁"的模式,没有私钥的人连尝试的入口都没有那么直接。
免交互。Git 是命令行工具,日常
push和pull频繁发生,如果每次都要输入密码,自动化脚本和 CI/CD 就无从谈起。配置密钥之后可以完全免密。可撤销。你换了电脑,或者怀疑私钥泄露,只要去远程平台删掉那把公钥即可。不用改 Git 账号密码,不会牵连其他服务。如果用的是密码认证,一旦密码泄露,你需要去改密码,还可能影响所有绑定该密码的服务。
更细粒度的控制。在公司和团队里,一个人可能有多个密钥,分别对应不同平台的多个账号,也可以在离职时单独吊销某一把。这种管理方式在密码时代是做不到的。
所以密钥配置不是 SSH 的附加功能,而是它在自动化时代能够成为 Git 传输默认协议的关键原因。
2.3 生成密钥时到底发生了什么:深入 ssh-keygen
打开终端执行ssh-keygen的时候,大多数人只是按回车回车回车,并没有认真理解这个过程。
默认情况下,ssh-keygen会在~/.ssh/目录(Windows 上是C:\Users\你的用户名\.ssh\)下生成两个文件。id_ed25519是私钥,id_ed25519.pub是公钥。私钥的权限被严格限制为只能由当前用户读写(在 Unix 系统上是 600 或 700),因为私钥一旦被其他人读取,就等于被盗走了身份。
关于密钥算法的选择,我强烈建议新手上手直接使用 Ed25519:
ssh-keygen -t ed25519 -C "你的邮箱或备注"
-Ed25519 是目前 OpenSSH 默认推荐的算法之一,密钥长度短、生成速度快、安全性强。
相比传统的 RSA 2048,Ed25519 的密钥更短,但安全强度更高。
GitHub 和 Gitee 这些主流平台早就支持 Ed25519。
如果要用 RSA,则建议至少使用-b 4096的位长,ssh-keygen -t rsa -b 4096 -C "你的邮箱"。
生成过程中会让你设置 passphrase,也就是私钥的密码。如果在这里直接留空,私钥就以裸文件形式保存在磁盘上,任何人拿到你的私钥文件都能使用它。如果设置了 passphrase,那么每次使用私钥时还需要输入这个口令,安全性更高。很多人嫌麻烦会留空,但这里有个折中方案:设置 passphrase,然后用ssh-add把私钥加进 SSH agent,这样只在开机后第一次使用时输入一次,之后会话期间都免密。
实际上ssh-keygen生成的是公私钥对,这一步不涉及任何远端服务器。所以哪怕你没有网络,也可以生成密钥,真正需要网络的是下一步:把公钥内容添加到平台上去。
3. 从生成到测试:Git 仓库 SSH 密钥配置全流程
3.1 环境准备:确认你的 OpenSSH 客户端可用
在开始配置前,先确认本机有没有可用的 SSH 客户端。
- Windows 10 1809 及更高版本的系统自带 OpenSSH 客户端,在 PowerShell 或 CMD 里输入
ssh -V能看到版本号。如果提示命令不存在,可以在"设置 -> 应用 -> 可选功能"里添加"OpenSSH 客户端"。 - macOS 和大部分 Linux 发行版默认就有 SSH 客户端,无需额外安装。
- 如果你装的是 Git for Windows,它的安装目录里也带了一套 SSH 工具,可以把 Git Bash 当作终端来操作。
这里有个容易乱的点:Windows 系统 PowerShell 里用的是系统 OpenSSH,Git Bash 里用的是 Git 自带的 SSH。两套工具的配置目录都在C:\Users\你的用户名\.ssh\,是共用的。但ssh-agent服务可能是各自独立的,导致你在 PowerShell 里用ssh-add加的密钥,在 Git Bash 里不一定生效。建议初学者固定使用一个终端环境,比如 Windows 上就统一用 Git Bash。
3.2 完整操作步骤:生成、部署、测试一气呵成
我这里以 GitHub 为例,但 Gitee、GitLab 的流程基本一模一样,只是平台入口位置略有差异。
第一步:生成密钥对
打开终端,执行:
ssh-keygen -t ed25519 -C "你的邮箱或任意备注"建议用-o参数来使用新的 OpenSSH 格式存储私钥,默认算法下现代版本会自动启用:
ssh-keygen -t ed25519 -o过程中会询问保存路径,默认是~/.ssh/id_ed25519,直接回车即可。接着会提示设置 passphrase,建议填一个,如果你不想每次 Git 操作都输密码,可以后续用 ssh-agent 记住它。
第二步:查看公钥内容
执行:
cat ~/.ssh/id_ed25519.pub在 Windows 上是:
type C:\Users\你的用户名\.ssh\id_ed25519.pub输出内容长这样:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... 你的邮箱或备注你需要把这一整行内容完整复制下来。注意不要用微信或某些即时通讯工具传输这个公钥文本,容易因为自动换行导致内容变化。可以把公钥文件用记事本打开后手动全选复制,或者直接在终端里选中复制。
第三步:在平台添加公钥
以 GitHub 为例,点右上角头像 -> Settings -> SSH and GPG keys -> New SSH key。Title 可以填"我的 Windows 笔记本"这类便于识别的名字,Key type 选择 Authentication Key,然后粘贴公钥内容,保存。
- Gitee 的入口是:设置 -> SSH 公钥。
- GitLab 的入口是:偏好设置 -> SSH 密钥。
第四步:本地测试连接
在终端执行:
ssh -T git@github.com第一次连接时会出现主机指纹确认提示:
The authenticity of host 'github.com (IP)' can't be established. ED25519 key fingerprint is SHA256:xxxxxx. Are you sure you want to continue connecting (yes/no)?这里输入yes回车即可。看到下面这种输出就说明连接成功:
Hi 你的用户名! You've successfully authenticated, but GitHub does not provide shell access.Gitee 的测试命令是ssh -T git@gitee.com,成功会提示Hi 用户名! You've successfully authenticated, but Gitee does not provide shell access.这句话的意思是:SSH 认证通过了,但 Git 平台不给你 shell 终端权限,只允许 Git 命令。
第五步:给 Git 仓库配置 remote 地址
如果是从零开始的新仓库,用 SSH 地址添加:
git remote add origin git@github.com:你的用户名/仓库名.git git push -u origin main如果已经有仓库但用的 HTTPS 地址,可以这样切换:
git remote set-url origin git@github.com:你的用户名/仓库名.git到这里,一套完整的 SSH 密钥配置就结束了。接下来每次push、pull都不会再让你输密码。
3.3 多平台多账号的 SSH config 配置
很多人不是只用一个平台。比如可能同时用 GitHub 放个人项目、Gitee 放国内项目、GitLab 放公司代码,甚至同一台机器上还要区分个人账号和公司账号。
如果你只有一个密钥对,直接让所有平台共用同一把公钥完全没问题。但如果你希望不同平台用不同的密钥,或者同一个平台上有多个账号,那就必须借助~/.ssh/config文件了。
这个文件的作用是:让 SSH 客户端知道,连接某个 Host 别名时使用哪个用户、哪个私钥文件。
举个实际例子。假设你有两个 GitHub 账号,一个是个人号,一个是公司号:
# 个人账号 Host github.com HostName github.com User git IdentityFile ~/.ssh/id_ed25519_personal # 公司账号 Host github-work HostName github.com User git IdentityFile ~/.ssh/id_ed25519_work注意Host字段是别名,HostName才是真正连接的服务器地址。个人账号直接用github.com,这样正常git clone git@github.com:xxx/yyy.git时会自动走 personal 那把私钥;公司账号用github-work这个别名,克隆时地址要写成git@github-work:公司组织名/仓库.git,SSH 看到 Host 是github-work,就会去读HostName github.com并匹配~/.ssh/id_ed25519_work。
这个配置文件经常让人踩坑的地方有两个:
Host写得太宽泛。比如写成Host *,就会匹配所有 SSH 连接,导致其他原本想用默认密钥的连接也强制使用指定私钥。- 权限不对。Windows 下很容易遇到
Bad owner or permissions on C:\Users\thinkpad\.ssh\config的报错,这个我在下一章专门讲。
4. 常见连接报错的完整排查链路
4.1 Permission denied (publickey):先分四种情况
这是出现频率最高的一条报错。我排查这类问题时,一般按照下面的顺序逐一排除:
远程平台是否部署了公钥?登录网页端查看账号的 SSH keys 列表,确认是否存在你本机对应的公钥。没有就添加,有就继续下一步。
本地是否存在私钥?执行
ls ~/.ssh/看有没有私钥文件。如果没有,说明你根本没生成过,返回上一章从生成开始。SSH 客户端是否使用了正确的私钥?如果私钥文件不是默认的
id_ed25519或id_rsa,而是自定义名称,比如my_github_key,那就需要显式指定。可以在~/.ssh/config里配置 IdentityFile,或者用命令临时指定。临时指定测试的方法:
ssh -i ~/.ssh/my_github_key -T git@github.com如果这条命令能成功,说明问题就是 SSH 没有选中正确密钥。
- 私钥是否被 ssh-agent 正确加载?如果你给私钥设置了 passphrase,
ssh-add ~/.ssh/id_ed25519可以把它加进 agent。查看已加载列表:
ssh-add -l如果显示The agent has no identities.说明没有加载任何密钥。Windows 用户如果发现 ssh-agent 服务没启动,在管理员 PowerShell 里执行:
Get-Service ssh-agent Set-Service -Name ssh-agent -StartupType Manual Start-Service ssh-agentGit 连接的本质是 SSH 客户端拿私钥去认证,所以这条排查链路一定要从"有没有密钥"到"用没用对密钥"逐层往下,不要跳过中间任何一层。
4.2 Windows 下的权限泥潭:Bad owner or permissions on config
这个报错在 Windows 用户中非常多见,尤其是手动用记事本创建过~/.ssh/config文件的人。
OpenSSH 在 Windows 上对配置文件权限的要求是:config文件不能被除当前用户和 Administrators 组以外的任何账户访问。但 Windows 文件系统默认继承的权限往往包含 Everyone 或 Users 用户组,于是 OpenSSH 直接拒绝使用这个配置。
修复方法如下:
icacls "C:\Users\你的用户名\.ssh\config" /inheritance:r icacls "C:\Users\你的用户名\.ssh\config" /grant:r "你的用户名:F"第一行去掉文件从父目录继承的所有权限,第二行把完全控制权只授予当前用户。执行完再跑一次ssh -T git@github.com就正常了。
我还想强调,这个报错的本质是"文件权限过于开放",不只是 config 文件,.ssh目录下的私钥文件同样可能存在这个问题。如果你修复了 config 权限,后面又遇到私钥报权限错误,用同样的icacls命令处理私钥文件即可。
4.3 Host key verification failed:不是密钥的问题,是指纹的问题
这条报错和前面说的认证密钥完全是两回事,它说的是服务器主机密钥校验失败。
SSH 客户端在一台新服务器第一次连接时,会把服务器的主机公钥指纹记录在~/.ssh/known_hosts文件里。之后每次连接,客户端都会比对服务器返回的指纹是否和记录的相同。如果不同,OpenSSH 会拒绝连接并报Host key verification failed。
出现这个错误的常见原因:
- 服务器的 SSH 服务重装过,主机密钥变了。
- 你连接的 IP 被别的服务器复用。
- 中间有人冒充服务器。
正常处理方式不是急着关掉验证,而是先确认真实情况。如果确认服务器没问题,删除 known_hosts 里对应的旧条目:
ssh-keygen -R github.com或者直接编辑 known_hosts 文件删掉相关行。下次连接时会重新提示确认指纹,输入 yes 即可。
4.4 连接超时、拒绝连接:网络层和端口层的问题
如果报错是Connection timed out或Connection refused,这和密钥配置就没有关系了,而是你根本没有触达服务器的 SSH 服务。
排查方向从下往上:
- 服务器是否开机、SSH 服务是否运行?
- 防火墙是否放行 22 端口?
- 企业在内网环境下是否有额外的网络安全策略拦截非标端口的出站连接?
- 仓库平台的 SSH 服务是否正常?
替换端口测试也是一种思路。某些平台支持通过 443 端口走 SSH 连接,GitHub 专门有这个能力:
ssh -T -p 443 git@ssh.github.com如果你的 22 端口被网络环境阻断,但 443 端口开放,可以改用ssh.github.com这个地址。把 remote 地址改成:
git remote set-url origin ssh://git@ssh.github.com:443/你的用户名/仓库名.git这个方案在很多受限网络环境下确实有效。但要注意,这是在极端场景下的变通手段,正常情况下没必要改。
4.5 测试连接成功,但 git push 依旧失败
还有一类隐蔽问题:ssh -T git@github.com明明显示认证成功,但git push依然报错。这种情况多半不是 SSH 的问题,而是 Git remote 地址配置有问题。
比如你可能把 HTTPS 地址、SSH 地址混在一起,或者 remote 里的用户名部分写错了。检查当前仓库的 remote:
git remote -v确保输出的地址是git@github.com:xxx/yyy.git这种格式,而不是https://github.com/xxx/yyy.git。如果是后者,执行前面提到的set-url修改即可。
另外,有些新仓库第一次 push 时用了main分支,但远端默认分支是master,也容易产生误导性的错误输出,这种情况和 SSH 无关,看清楚报错里的分支信息再判断。
5. 密钥使用中的进阶细节:多账户、known_hosts 与 SSH agent
5.1 多账户切换的日常操作方式
上一章的 config 配置解决了"多把私钥如何区分"的问题,但实际使用中还有一个细节容易被忽略:不同的 SSH 连接场景,git 提交身份的 user.name 和 user.email 应该如何对应。
SSH 密钥解决了"认证"问题,Git 的 user.name/user.email 解决的是"提交记录署名"问题。两者独立。你可以用 GitHub 的密钥连接仓库,但提交时署名成自己公司的邮箱,这完全能发生,只是世界各地的维护者看到你的提交会觉得很奇怪。
所以多账户时,我建议在仓库目录下设置局部配置:
git config user.name "你的昵称" git config user.email "你的邮箱"不带--global的配置只对当前仓库生效。这是最干净的做法,比全局改来改去省心得多。配合~/.ssh/config的 Host 别名,每次克隆时只要注意地址用的是哪个 Host,推送和署名就会自然落到正确身份上。
5.2 known_hosts 文件的作用与安全边界
~/.ssh/known_hosts是 SSH "信任第一次连接"机制的产物。它没有复杂的密钥管理体系,就是把你第一次接触到的服务器指纹记下来,之后每次对比,从而在传输层面降低了被中间人攻击的风险。
不要轻易去删这个文件。如果删掉整个 known_hosts,下次连接所有服务器时都会被询问是否信任。这个文件里的内容并不算敏感,泄露出去影响不大,但被恶意篡改的风险不容忽视:如果攻击者能在你不知情的情况下改写 known_hosts,他就能伪装成你信任的服务器,诱导你输入密码或部署新的公钥。所以这个文件的权限同样应该保持严格,不要用管理员权限的编辑器去随意修改它。
5.3 ssh-agent 的加载机制与启停艺术
ssh-agent 的作用是帮你记住已解锁的私钥。它的工作原理是,私钥的完整内容被读取进内存后,之后的 SSH 认证请求只需要 agent 用内存中的密钥完成签名,不需要再次读取磁盘文件,也不需要再输入 passphrase。
这带来两个好处:
- 设置了 passphrase 的私钥不用反复输密码。
- 私钥内容不会重复暴露给每个要使用它的程序。
但如果你的 ssh-agent 里加载了很多密钥,服务器验证时会出现一个问题:客户端会按照IdentityFile的配置顺序依次尝试。如果某个密钥尝试次数太多导致服务器拒绝,可能拖慢连接速度。解决方式是精确配置 config 文件,让每个 Host 只使用一把密钥。
在 macOS 上,ssh-add --apple-use-keychain ~/.ssh/id_ed25519可以把私钥存入系统钥匙串,重启后自动加载。Windows 上如果希望持久化,可以把ssh-add放进启动目录,或者使用内置的 SSH Agent 服务并配置自动加载。
5.4 密钥备份与隐私安全
私钥是一份极其敏感的文件。它一旦泄露,就等于把访问你所有账号对应仓库的能力交给了别人。而且 Git 仓库不像银行账户,被盗刷后很难追溯,攻击者可以在你毫不知情的情况下克隆你的私有代码、向项目里植入恶意提交。
所以有几条原则值得记住:
- 永远不要把你的私钥提交到任何 Git 仓库。
- 不要在聊天工具、网盘、在线笔记里备份私钥。
- 换电脑时,最安全的迁移方式是先生成新密钥对,把新公钥添加到平台,再删除旧公钥。而不是复制私钥文件到处走。
- 如果怀疑私钥泄漏,最好的应对是删除平台上对应的公钥,重新生成,而不是抱着侥幸心理继续用。
有些人会问,那我做了备份是不是更好?说实话,私钥备份本身就是个伪需求。你真正需要备份的是访问权限的可用性,而重新生成并部署新公钥可以在几分钟内完成。备份私钥带来的风险收益比非常不划算。
5.5 同一套知识能不能用到 VSCode 远程开发上
很多人会问:VSCode 连接远程服务器开发时也用 SSH,配密钥的方法和 Git 配置一样吗?
答案是大致一样。VSCode 的 Remote-SSH 插件依赖本机 OpenSSH 客户端和~/.ssh/config配置。你在 config 里写好 Host、HostName、User、IdentityFile,VSCode 就会用这套配置帮你建立远程连接,而且可以复用你已经加载进 ssh-agent 的密钥。
比如你在公司工作站上配置了一个别名:
Host dev-server HostName 192.168.1.100 User ubuntu IdentityFile ~/.ssh/id_ed25519_work ForwardAgent yes在 VSCode 的 Remote Explorer 里直接选择dev-server就能连接。这个过程中的密钥认证逻辑和 Git 仓库连接完全一致。也就是说,学会理解 SSH 协议与密钥配置之后,你不仅解决了 Git 仓库连接失败的问题,还能顺手打通远程开发这条线。很多开发者从"照着博客敲命令"到"能独立配置 SSH",就是从这个点上开始突破的。
回到最开始那个Permission denied (publickey)的报错。现在再看到它,你应该能理解它背后的完整链条了:服务器要确认你是不是合法访问者,你手上有没有对应的私钥,你愿不愿意出示,以及你有权访问哪些仓库。把这条链路想清楚,SSH 对你来说就不再是一堆零散的命令,而是一套清晰可复现的流程。我个人在设计配置规范时,会把所有密钥按用途命名好,加上-C备注,在每个平台后台都保留对应的部署记录,这样无论过多久再回头看,都能一眼认出这把钥匙是给谁用的。希望这篇内容也能帮你把 SSH 这块地基打得扎实一些。