一次搞懂 SSH、GitHub 与 `~/.ssh` 里的那些文件
这次你从 “git push 提示登录失败、Permission denied (publickey)” 一路排查到成功推送,其实已经把 SSH 的关键知识都走了一遍。
一、为什么 git push 会要求“登录”?
现在 GitHub 已经不再接受账号+密码的方式,推荐两种认证方式:
- SSH key(最常用,也最省心)
- Personal Access Token(PAT) + HTTPS
你遇到的是 SSH 场景下的错误:
git@github.com: Permission denied (publickey).
含义很简单:
“我只接受用公钥认证,但你给我的这些钥匙里,没有一把是我认识的。”
也就是说:本地用的私钥,和 GitHub 那边保存的公钥没配上。
二、SSH 密钥对:私钥 + 公钥
在本地生成 SSH 密钥时,我们用的命令类似:
ssh-keygen -t ed25519 -C "your_email@example.com"
各部分含义:
ssh-keygen:生成 SSH 密钥对的工具-t ed25519:使用 ed25519 算法(比传统 RSA 更推荐)-C "...":给这把钥匙加一个“备注”,通常写邮箱,方便以后识别
生成后会在 ~/.ssh 下出现一对文件:
- 私钥:例如
id_ed25519 - 公钥:例如
id_ed25519.pub
关系可以理解为:
- 私钥:只在你自己电脑上保存,绝对不能对外泄露
- 公钥:可以复制到 GitHub 或服务器,用来识别“这台机器”
认证过程大致是:
- 你用私钥在本地做签名
- GitHub 用保存的公钥验证签名
- 如果能验证通过,就说明你确实拥有对应的私钥,身份 OK
三、~/.ssh 目录里的常见文件
典型情况下,你的 ~/.ssh 下会有这些文件(名字略有不同没关系):
- 私钥
id_ed25519github
- 公钥
id_ed25519.pubgithub.pub
- 配置文件
config
- 信任主机列表
known_hostsknown_hosts.old
它们的作用分别是:
id_ed25519/github:本机私钥,SSH 认证时用id_ed25519.pub/github.pub:公钥,要复制到 GitHub 等远端服务config:SSH 的“路由表”,告诉 SSH:- 访问哪个 Host 时,用哪把私钥、哪个用户名等
known_hosts:- 记录“我信任哪些远程主机指纹”
- 第一次连接某个主机时会问
yes/no,你选yes后就写入这里 - 以后对比指纹,防止中间人攻击
四、~/.ssh/config:SSH 的“自动配置表”
~/.ssh/config 文件的作用,是给 SSH 定义按 Host 维度的规则,例如:
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/github
IdentitiesOnly yes
这段规则可以这样理解:
- 当你访问
github.com:- HostName:实际连接的主机是
github.com - User:用
git这个用户名(GitHub SSH 固定是 git) - IdentityFile:只用
~/.ssh/github这把私钥 - IdentitiesOnly yes:不要乱试别的钥匙
- HostName:实际连接的主机是
有了这段配置后:
- 你只需要写
ssh -T git@github.com或直接git push - SSH 会自动:
- 识别这是
github.com - 只拿出
~/.ssh/github私钥去认证
- 识别这是
- 只要这把私钥对应的公钥已经添加到 GitHub 账号中,认证就能一次通过
五、没有配置 Host 时,SSH 默认怎么做?
如果你完全不写 Host github.com 这类配置:
- SSH 会按照默认规则,从“默认密钥文件 + ssh-agent 中的 key”里依次尝试几把私钥
- 让远端服务一个个试图用它保存的公钥来验证
- 如果在限定次数内,有一把能配上,就通过;都配不上,就
Permission denied (publickey)
问题在于:
- 你可能有多把 key(私钥很多),但 GitHub 只认识其中一把
- SSH 不一定会刚好选对那把;或者试错次数超过远端限制,直接被拒
所以我们在 config 里针对 github.com 写清楚 IdentityFile,就是为了:
“访问 GitHub 就只用这把你已经在 GitHub 配过的私钥。”
这也是你在补全 config 后,问题立刻解决的根本原因。
六、ssh -T git@github.com 和那句“does not provide shell access”
当你执行:
ssh -T git@github.com
如果配置正确,会看到类似提示:
Hi your-username! You've successfully authenticated, but GitHub does not provide shell access.
这句话的含义是:
- 认证结果:你已经用 SSH key 成功通过身份验证 ✅
- 限制说明:GitHub 不像一台普通 Linux 服务器,不允许你登录进去拿到 shell,只能通过 Git 协议进行拉取 / 推送等操作
对我们来说,只要看到这句话,就可以认为 SSH 配置成功,可以继续 git push 了。
七、SSH + GitHub 的完整闭环
总结一下从配置到推送的完整流程:
-
本地生成 SSH 密钥对
ssh-keygen -t ed25519 -C "your_email@example.com" # 在提示保存路径时,如果已有 id_ed25519,想新生成一把: # 输入一个新文件名,比如:/Users/you/.ssh/github -
把公钥添加到 GitHub
cat ~/.ssh/github.pub- 复制输出内容
- 打开 GitHub → Settings → SSH and GPG keys → New SSH key
- 粘贴并保存
-
在
~/.ssh/config中为 GitHub 指定这把 keyHost github.com HostName github.com User git IdentityFile ~/.ssh/github IdentitiesOnly yes -
确认远程仓库使用 SSH 地址
cd /path/to/your/repo git remote -v # 确认是: # origin git@github.com:username/repo.git (fetch) # origin git@github.com:username/repo.git (push) -
测试 SSH 连接
ssh -T git@github.com出现
successfully authenticated, but GitHub does not provide shell access即成功。 -
正常使用 git 推送
git push
八、几个容易踩坑的小点
-
在
ssh-keygen提示保存路径时不要随便回车- 已经有
id_ed25519时,直接回车会覆盖旧 key - 想要多一把独立的 key,一定要输入新文件名(带绝对路径)
- 已经有
-
在
ssh-keygen中输入~/.ssh/xxx有时会报 “No such file or directory”- 有些环境下,这个输入不会自动展开
~ - 最稳妥的写法是:
/Users/你的用户名/.ssh/xxx
- 有些环境下,这个输入不会自动展开
-
多个 key 混在一起时一定用
config指定 Host- 否则 SSH 默认“轮询尝试”,一旦超过服务器允许的 key 尝试次数,会直接拒绝
通过这次实战,你已经把 SSH + GitHub 这一块的核心知识都走通了。以后只要记住这几点:
- 一对密钥:本地保私钥,远程存公钥
config决定“去哪用哪把钥匙”- 看到 “successfully authenticated, but GitHub does not provide shell access” 就说明 SSH OK,可以放心
git push
如果之后你在别的机器上也要配 GitHub,只要复刻这一整套流程,很快就能搞定。
更多推荐



所有评论(0)