Permission denied (publickey) 怎么解决?Git 推送失败的 6 种原因与修复
现象:git 操作直接被拒
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
一行结论:SSH 认证失败——服务器不认识你提供的公钥。这个错误和密码无关(publickey 方式不用密码),是「你手里的钥匙」和「服务器登记的锁」对不上,或者你根本没递出钥匙。
先做一件事:ssh -T 直接测认证
绕过 git,直接测 SSH 通道,能拿到最干净的错误信息:
ssh -T git@github.com
# 成功:Hi yourname! You've successfully authenticated...
# 失败:git@github.com: Permission denied (publickey).
# 加 -v 看详细过程:尝试了哪些密钥、服务器接受哪些认证方式
ssh -vT git@github.com 2>&1 | grep -E 'Offering|identity file|denied'
-v 输出里的 Offering public key: /Users/you/.ssh/id_xxx 是关键——它列出的是实际递出去的钥匙。如果列表里没有你以为在用的那把,直接跳到原因 2。
六种原因,按概率排序
1. 本机没有密钥(新电脑最常见)
ls ~/.ssh/
# 有 id_ed25519 / id_ed25519.pub 或 id_rsa / id_rsa.pub → 已有
# 什么都没有 → 生成一把
ssh-keygen -t ed25519 -C "your_email@example.com"
# 一路回车(或设置口令),然后启动 agent 并加载
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
生成后把 .pub 文件内容(只有公钥可以外发,私钥永远不离开本机)添加到 GitHub:Settings → SSH and GPG keys → New SSH key。
2. 密钥在,但 agent 没加载
ssh-add -l
# "The agent has no identities." → 没加载
ssh-add ~/.ssh/id_ed25519
macOS 可以把密钥信息写进 ~/.ssh/config 免去每次手动 add:
Host github.com
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519
3. 公钥没加到平台(或加错了账号)
GitHub 的公钥是账号级的:加在 A 账号下的钥匙,推 B 账号的仓库当然被拒。还有一种情况:同一把公钥已经绑在另一个 GitHub 账号上——GitHub 不允许同一公钥绑定多个账号,部署密钥同理。多账号场景见原因 4。
公司 GitLab / Gitee / 自建 Git 服务器各有各的公钥添加入口,确认你加对了平台。
4. 多账号/多密钥:递出去的不是那把钥匙
本机有公司钥匙 + 个人钥匙时,SSH 默认按顺序尝试,经常递错。用 ~/.ssh/config 按_host_ 别名路由:
# 个人 GitHub
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_personal
IdentitiesOnly yes
# 公司 GitHub 账号走别名
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_work
IdentitiesOnly yes
IdentitiesOnly yes 是关键——强制只用指定的钥匙,不把其他钥匙都递一遍。然后 remote URL 用别名:
git remote set-url origin git@github-work:company/repo.git
5. Deploy key 的权限边界
仓库 Settings → Deploy keys 添加的公钥只对当前仓库有效:用它 clone 别的仓库、或想 push 但添加时没勾选 write access,都会 publickey 被拒。CI 机器上常见的坑:一台 runner 用同一把 deploy key 想拉多个仓库——用 organization 级的 Deploy keys 或 machine user 账号代替。
6. remote URL 写错(https 和 ssh 混着用)
git remote -v
# origin git@github.com:user/repo.git → 走 SSH,用本文方法排查
# origin https://github.com/user/repo.git → 走 HTTPS,报错会要求密码/token,不是 publickey
大小写、组织名拼写、.git 结尾缺失都会导致「仓库不存在」和「认证失败」混淆。另外 GitHub 组织开启了 SSO 的,个人钥匙还需要对该组织授权一次(SSO → Authorize)。
为什么有时密码登录也被提示 publickey?
错误括号里的 publickey 是服务器允许的认证方式列表。如果显示 Permission denied (publickey,password),说明两种方式都试过且都失败了——SSH 会按服务端允许的方式依次尝试,全挂了才报错。看括号内容能知道服务端开了哪些门。
排查清单
ssh -T git@github.com— 直连测试,错误信息最干净ssh -vT ... | grep Offering— 实际递出了哪把钥匙?ls ~/.ssh/+ssh-add -l— 钥匙存在吗?加载了吗?- 公钥加在目标平台、目标账号(或仓库 deploy key)上了吗?
- 多把钥匙:
~/.ssh/config分 Host 别名 +IdentitiesOnly yes git remote -v— URL 拼写、协议(ssh vs https)核对
本文由 ToolVault 工具匣 提供。相关工具:Linux 命令速查、密码生成器、JWT 解码。相关阅读:npm 网络问题换源指南、端口被占用排查。访问 首页 查看更多开发者工具。
相关工具
相关文章
npm ERR! ERESOLVE:peer dependency 冲突的四种解决策略
npm install 报 ERESOLVE unable to resolve dependency tree 怎么办?理解 peer dependency 的设计意图,掌握四种解决策略(版本修复 / legacy-peer-deps / overrides / dedupe)及其适用场景与风险。
error:0308010C digital envelope routines::unsupported 怎么解决?Node 17+ 跑老项目的三种修法
Node 17+ 启动 webpack 4 老项目报 error:0308010C:digital envelope routines::unsupported?根因是 OpenSSL 3.0 移除了 MD4 哈希。本文给出 --openssl-legacy-provider 临时方案、升级 webpack 5 根治方案和锁定 Node 16 的取舍。
ECONNREFUSED 连接被拒绝怎么排查?5 种原因一次讲清(含 Docker 场景)
Node/Java/curl 报 connect ECONNREFUSED 127.0.0.1:3306 怎么办?含义是目标端口上没有任何进程在监听。覆盖服务未启动、端口记错、只监听 127.0.0.1、Docker 容器互连、防火墙五种根因,附 ss/lsof 排查命令。