很多人第一次接触 GitHub SSH 配置时,都会照着官方文档走一遍:生成密钥、复制公钥、粘贴到网页后台、再敲一句ssh -T git@github.com验证。我这么干过无数次,换电脑要弄一次、重装系统要弄一次、给新成员配环境还要弄一次。直到我把日常操作切到 GitHub CLI(也就是gh)之后才意识到,手动配 SSH 这件事,其实根本不该重复这么多次。
这篇文章就把我自己的折腾过程、最后的方案、以及过程中踩过的坑完整写出来。如果你刚接触 Git 和 GitHub,或者已经在用 SSH 但每次都配得心烦,可以顺着这条思路走一遍。文章里涉及的实际命令、配置代码块、报错对照,都是可以直接抄作业的级别。
1. 手动配 SSH 的那些坑,我全都踩过
先别急着上 GitHub CLI,我先把以前手动配 SSH 的完整路径捋一遍。这样你才能明白我为什么说“不再手动配”了,也能在对比中理解 CLI 到底省掉了哪些步骤。
1.1 常规流程看着简单,实操全是细节
按照 GitHub 官方文档,手动配置 SSH 的步骤其实就四步:
- 打开终端,执行
ssh-keygen -t ed25519 -C "你的邮箱",一路回车生成密钥对。 - 复制
~/.ssh/id_ed25519.pub里的内容,粘贴到 GitHub 的 Settings -> SSH and GPG keys 页面。 - 执行
ssh -T git@github.com验证,看到 “Hi xxx! You've successfully authenticated” 就算成功。 - 把远程仓库地址改成 SSH 格式,比如
git@github.com:user/repo.git。
这套流程看着没问题,但实操里的坑特别多。比如ssh-keygen执行之后,系统会问你密钥保存路径,很多人直接回车默认存到~/.ssh/id_ed25519,这没问题。但如果你的电脑上已经有一个旧密钥,它会提示 “Overwrite (y/n)?” 一个走神按了 y,旧密钥就没了。而那个旧密钥可能还挂在公司 GitLab 上、绑着你服务器登录权限、甚至关联着某个 CI 系统,第二天公司同事就来找你:“部署怎么挂了?”
我自己就干过这事,所以现在看到ssh-keygen的覆盖提示都会一哆嗦。正确做法是先ls ~/.ssh/看看目录里有什么,再决定是复用还是新建单独的文件名。
1.2 报错信息对新手非常不友好
手动配 SSH 最让人崩溃的是排错。最常见的是这句:
git@github.com: Permission denied (publickey).第一次见到这行字的人基本是懵的。“我明明刚把公钥贴上去了啊,为什么还拒绝?” 而 GitHub 官方给的排查清单长到让人怀疑人生:有没有运行ssh-agent、密钥有没有添加到 agent、公钥有没有复制完整、有没有在网页端点保存、你的~/.ssh/config有没有写错…… 每一项都要单独测一遍。
我当时为了排查这个问题,把官方文档来回翻了三四遍。后来才发现原因是公司的安全软件把私钥权限改掉了,文件变成了 644。SSH 出于安全考虑,根本不会去读权限过于宽松的私钥文件,但问题是——报错信息里完全看不出来是这个原因。
1.3 多账号场景下配置复杂度飙升
如果你只有一个 GitHub 账号、一台电脑,手动配 SSH 还算能忍。但我相信很多人和我一样,有个人 GitHub、有公司账号,甚至还有客户项目单独的账号。要在同一台电脑上让多个账号互不干扰,就得去改~/.ssh/config。
典型的多账号配置长这样:
Host github.com-personal HostName github.com User git IdentityFile ~/.ssh/id_ed25519_personal Host github.com-work HostName github.com User git IdentityFile ~/.ssh/id_ed25519_work配置好后,你还是得手动记住:个人项目要用git@github.com-personal:user/repo.git克隆,工作项目要用git@github.com-work:org/repo.git克隆。漏一个字母,SSH 就分不清该拿哪把钥匙,又回到Permission denied。
这种手动管理方式在账号少的时候是可行的,但一旦多了,每次给新项目配 remote 都是一次心智负担。我后来甚至专门写过小抄贴在自己工位上,记哪类仓库用哪个 Host 别名。到这一步,我已经很确定必须换工具了。
2. GitHub CLI 到底改了什么
GitHub CLI(命令行工具gh)并不只是把网页上的操作搬到终端里,它在认证层面彻底改变了我们和 GitHub 打交道的方式。搞清楚这点,你就理解我为什么说“不再手动配 SSH”了。
2.1 一句话说清 gh 的认证模型
在手动配 SSH 的模式下,GitHub 需要记住你的公钥,你本地保留私钥,每次 Git 操作时用“私钥签名”来证明身份。这套“公钥-私钥”机制非常安全,但问题在于它要求你亲自完成密钥全生命周期管理:生成、分发、存储、轮换。
gh的做法完全不同。它走 OAuth 授权流程——你在浏览器里登录 GitHub,授权给gh一个访问令牌(token)。之后gh拿这个 token 去代替你呼叫 GitHub API,能做你在网页上能做的几乎所有事情,包括管理 SSH 密钥本身。
最关键的是:gh auth login会顺带帮你把 Git 的认证方式直接配置妥当。它可以把 HTTPS 推拉代码时的账号密码替换成 token 自动管理,或者直接调用 GitHub API 把你的 SSH 公钥上传好。你不再需要打开网页、粘贴公钥、点保存,这三步高频操作直接消失。
2.2 它到底怎么接管 SSH 管理的
你可能要问:“那如果我还是想用 SSH 协议连接呢?gh 能做什么?” 答案是它能帮你把最麻烦的几步全部自动化。
在gh auth login的过程中,如果你选择 SSH 作为 Git 协议,它会问你“想不想生成一个新的 SSH 密钥?”。选 Yes 后,gh自动执行ssh-keygen生成密钥对,然后直接把公钥内容发送到 GitHub API 注册。全程只有两个输入:一是回车确认密钥存储位置,二是确认要不要给密钥加点口令。整个流程跑完,你的 GitHub SSH keys 列表里已经多了一把钥匙,而且它写的标题是类似“GitHub CLI”的名字,一眼就能认出来。
对比一下:以前手动流程里需要在终端和浏览器之间来回切换,现在变成了终端内的单线操作,不需要浏览器,不需要复制粘贴。这一步至少节省 5 分钟,而且零失误可能。
2.3 更推荐普通人直接走 HTTPS 协议
说实话,自从开始用gh之后,我新电脑上就再也没生成过面向 GitHub 的 SSH 密钥。原因是gh auth login时直接选 HTTPS,它会把 Git 使用的凭据助手(credential helper)配置成gh auth git-credential。
什么意思呢?当你执行git push origin main时,Git 会向凭据助手要账号密码,gh就把自己的 token 递上去,GitHub 服务端识别之后,直接放行。全程看不到密码输入框,也不会要求你配任何密钥文件。这就是我实际在用的状态——GitHub 这边完全不需要 SSH,所有推送拉取都走 HTTPS,认证由gh自动完成。
有些人可能会担心:“HTTPS 推送代码会不会每次都要输用户名密码?” 其实不会。配置好凭据助手后,gh会自己管理和刷新 token,普通开发者根本感知不到认证过程。别被早年 Git 时期每次 push 都要输入密码的旧经验绑架,今时不同往日。
3. 从零跑一遍 gh auth login,手把手实操
讲完原理,我带你实走一遍流程。新电脑收到手,到能正常git push代码,用gh只需要 5 分钟。下面按步骤拆解。
3.1 安装 gh:不同系统的简要命令
gh的安装方式在官方文档里有完整说明,我这里只列最常用的几种:
- macOS(Homebrew):
brew install gh- Ubuntu / Debian(官方 apt 源):
(type -p wget >/dev/null || (sudo apt update && sudo apt-get install wget -y)) \ && sudo mkdir -p -m 755 /etc/apt/keyrings \ && wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \ && sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \ && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \ && sudo apt update && sudo apt install gh -y- Windows(winget 或 Scoop):
winget install --id GitHub.cli # 或者 scoop install gh安装完跑一句gh --version验证即可。如果提示command not found,多半是 PATH 没生效,重启终端通常能解决。这里要提醒一句:我之前在 Ubuntu 上直接apt install gh,结果装到一个老版本,好多新命令不可用,后来才补了官方源。如果你系统默认源里的版本不是你想要的,最好别偷懒。
3.2 登录流程:选择“HTTPS 还是 SSH”的关键节点
安装完成后,核心命令就是:
gh auth login执行后会进入一个选项流程。下面我用实际的选项顺序说明一下:
第一问:
What account do you want to log into?选GitHub.com。除非你要连 GitHub Enterprise 服务器,否则别选第二个。第二问:
What is your preferred protocol for Git operations?这里是关键节点。两个选项:
HTTPS:推荐。gh会接管 Git 认证,以后不需要任何 SSH 密钥。SSH:如果你公司内部规定必须走 SSH 端口,或者你的托管服务只放行 22 端口,可以选这个。选完后gh会接着问你是否生成新密钥并上传到 GitHub,跟着提示走即可。
我自己在公司电脑上选 HTTPS,因为最省事;Home Server 上因为要跑自动化脚本,我选 SSH,让gh自动上传密钥,然后用密钥去克隆私有仓库,这样脚本里不会出现 token 之类的敏感信息。
第三问:
Authenticate Git with your GitHub credentials?选Yes,这步决定之后git push/pull是否免密。如果这里选了 No,你将来还是会被反复要求输入密码,所以别省这一次选择。第四问:
How would you like to authenticate GitHub CLI?推荐选Login with a web browser。它会给出一串一次性代码,并自动打开浏览器。你粘贴代码、点授权、回到终端,全程不到 30 秒。如果你在无图形界面环境(比如纯 Linux 服务器),可以选Paste an authentication token,这需要先去 GitHub 网页上生成 Personal Access Token,复制进来即可。
浏览器授权完成后,终端会显示类似Logged in as yourname,整个登录流程就结束了。
3.3 登录后的验证和 Git 配置检查
登录成功不代表 Git 也通了。你需要确认两件事。一是在终端里跑:
gh auth status这个输出会显示你登录了哪个账号、Git 协议用的是 HTTPS 还是 SSH、有没有配置 git 凭据助手。二是在新目录里克隆一个你的私人仓库试试。这里有个小窍门:gh自带仓库克隆命令,不需要先去 GitHub 网页复制 URL。
gh repo clone yourname/private-repo这个命令会直接下载仓库。如果仓库是私有的,你就能立刻感觉到认证已经被处理好了,完全没有“输入用户名密码”的环节。跑通这步之后,你在该目录里执行git push、git pull,都会自动走gh的认证通道。
3.4 顺带把日常操作效率也拉满
既然已经装好了gh,就顺手把日常高频操作也一起用起来。我平时最常用的是这么几个:
gh repo create my-repo --public --clone gh pr create --title "xxx" --body "yyy" gh pr merge --squash gh issue list --assignee @me gh release create v1.0.0 --generate-notes这些命令能让你减少在网页和终端之间来回切换的次数。特别是gh pr create,当你在工作分支上写好代码后,一行命令就能生成 Pull Request,终端里会直接返回一个可点击链接。团队评审流程会因此顺畅很多,因为你在提 PR 时还能直接在命令行里写好模板化的描述。
gh还有一个很实用的功能叫gh alias set,能把常用长命令做成短命令。比如我想快速看当前仓库的 CI 状态,可以设:
gh alias set ci "run list --limit 10"之后执行gh ci就好了。
4. 如果还是必须用 SSH,这些核心原理你必须懂
我在上一节里推荐 HTTPS +gh接管认证,这是绝大多数人的最优解。但有些场景确实绕不开 SSH,比如连接你自己的 Linux 服务器、在路由器或 NAS 上做免密登录、或者在 CI 环境里用部署密钥。所以即使你现在不用 SSH 拉 GitHub,我也建议把下面几块核心知识吃透,因为它们是通用技能,和 GitHub CLI 无关。
4.1 密钥文件权限是第一个审查对象
先说一个出现频率最高的坑:私钥文件的权限太宽松,SSH 客户端直接拒绝使用。很多人从 Windows 上把密钥文件拷贝到 Linux 服务器,或者从压缩包里解压出来,文件权限经常变成 644(即其他用户可读),此时 ssh 命令会直接忽略这把私钥,视为不安全。
正确权限应该是:
chmod 700 ~/.ssh chmod 600 ~/.ssh/id_ed25519如果你用的是 macOS 且开启了 iCloud 同步,偶尔会遇到文件在云盘里兜了一圈后权限被改掉的情况。修复办法也一样,重新执行chmod即可。
检查密钥是否被正确识别,可以使用:
ssh -vT git@github.com加-v后输出的日志里会明确显示Offering public key还是Trying private key file。如果日志里连Offering都没出现,说明 SSH 客户端压根没读到你的密钥文件,基本就是路径或者权限问题。
4.2 ssh-agent:帮你免去频繁输入口令的麻烦
如果你生成密钥时设置了 passphrase(口令),每次 SSH 连接时都会要求输入一次,这在需要频繁推送时极其烦人。解决办法是让ssh-agent帮你在会话期间记住口令。
标准启动方式:
eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_ed25519执行ssh-add -l可以看到当前 agent 里管理了哪些钥匙。如果你用的是 macOS,还可以加--apple-use-keychain参数,让密钥口令存入系统钥匙串,重启电脑后也不用重新输入。
这里有个常见误区:以为只要设置了 passphrase 就一定要每次输。其实ssh-agent的存在就是为了解决这个问题的,它相当于一个帮你保管解密后私钥的临时管家。不过有一点要注意:ssh-agent里的钥匙是内存级的,电脑重启就清零,所以建议在 shell 配置文件(如.bashrc或.zshrc)里加上自动执行的逻辑。
4.3 多账号配置的正确姿势
上一节提到的多账号 SSH config 写法,这里我再给出一个更完整的例子:
Host gh-personal HostName github.com User git IdentityFile ~/.ssh/id_ed25519_personal IdentitiesOnly yes Host gh-work HostName github.com User git IdentityFile ~/.ssh/id_ed25519_work IdentitiesOnly yes这个配置里的关键是加上了IdentitiesOnly yes。不加这句话,SSH 会把ssh-agent里所有钥匙都一一拿出来试,有时候会把错误的公钥发送给 GitHub,导致权限校验失败。加上之后,它只会用指定的IdentityFile,多账号场景立刻清爽很多。
使用这个配置时,克隆命令就要写成:
git clone git@gh-personal:yourname/repo.git git clone git@gh-work:yourorg/repo.git如果你发现配置完某个仓库连不上,先看 remote 地址里的 Host 别名对不对:
git remote -v4.4 测试连接的正确方法:会用 -T 参数
测试 SSH 连接 GitHub 时,正确的命令是:
ssh -T git@github.com如果成功,会看到:
Hi yourname! You've successfully authenticated, but GitHub does not provide shell access.注意这个提示里的“does not provide shell access”是正常的,GitHub 的 SSH 服务只承载 Git 操作,不是给你开终端用的。有人看到这句话以为自己配置出问题了,其实没有。
-T参数的作用是禁用伪终端分配,因为 GitHub 不需要也不允许交互式 shell,加上它能让测试更快返回结果。很多人不加-T也能连上,但等待时间可能更长,而且输出内容会稍有不同,建议养成规范习惯。
5. 常见问题速查:认证失败、连接超时、多账号踩坑
最后这部分直接给速查表。每一条都是我自己或者身边朋友实际碰到过的,包含现象、原因、处理方法,适合收藏后当检索手册用。
5.1 git 推送时要求输入密码,或者认证失败
如果你配置了gh仍然出现密码输入框,或者报错:
fatal: could not read Username for 'https://github.com': terminal prompts disabled多数原因是凭据助手没配置成功。手动确认一下:
git config --global credential.helper如果输出为空,说明gh的配置没写进去。手动修复:
gh auth setup-git这条命令会重新配置gh作为 Git 的凭据助手,跑完后再试一次 push。
5.2 ssh: connect to host github.com port 22: Connection timed out
如果你坚持用 SSH 但 22 端口不通(典型表现是连接超时),可以考虑改用 SSH over 443。GitHub 官方支持ssh.github.com:443这个入口,配置方法是在~/.ssh/config里写:
Host github.com HostName ssh.github.com Port 443 User git注意此时 Host 仍然写github.com,这样你不需要改 remote 地址里的仓库 URL。修改前建议先测一下 443 端口出网是否正常,再决定是否切换。这个方案对身处限制外连端口的办公网络场景很有用,也是 GitHub 官方明确支持的调试手段。
5.3 git@github.com: Permission denied (publickey)
这个问题我在第一节里提过,这里展开完整的排查顺序:
- 执行
ls -la ~/.ssh/,确认密钥文件是否存在。 - 执行
chmod 600 ~/.ssh/id_ed25519和chmod 700 ~/.ssh/,修正权限。 - 执行
ssh-add -l,如果提示The agent has no identities,执行ssh-add ~/.ssh/id_ed25519。 - 执行
ssh -vT git@github.com,查看日志中Offering public key的出现情况。 - 如果日志里显示已经向 GitHub 发了密钥但仍被拒绝,去 GitHub 网页检查公钥内容是否和本地
~/.ssh/id_ed25519.pub完全一致,尤其在结尾部分容易少复制一个字符。
5.4 常见的 HTTPS 证书报错怎么处理
如果你在git clone时遇到:
server certificate verification failed. CAfile: none CRLfile: none这种报错常见于内部代理或自建根证书环境。不推荐直接关掉 SSL 验证(也就是GIT_SSL_NO_VERIFY=true),因为那等于把 Git 的传输安全彻底暴露。更合理的做法是先确认你的系统根证书库是否需要更新,或者联系网络管理员,把内部 CA 证书装有可信列表中。
如果你只是临时拉取一个公开仓库着急用,也可以临时用-c http.sslVerify=false执行一次,但问题解决后应改回默认值。
5.5 使用 VSCode 远程开发时的 SSH 注意点
VSCode Remote-SSH 是另一个高频场景,但它连的是你自己的远程服务器,不是 GitHub。很多人会在这两套 SSH 体系之间绕晕。关键区分在于:
- 连接 GitHub 时,你面对的是
git@github.com,身份验证走的是 GitHub 账户里登记的 SSH 公钥。 - 连接自己的 Linux 服务器时,你面对的是
root@your-server-ip或普通用户,身份验证走的是服务器上~/.ssh/authorized_keys中登记的公钥。
如果你已经为 GitHub 生成过密钥,想在同一台电脑上登录服务器,不必再生成新密钥,直接把这个公钥追加到服务器的authorized_keys即可:
cat ~/.ssh/id_ed25519.pub | ssh user@your-server "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"VSCode 里配置远程连接时,也强烈建议在连接前先测试一遍命令行 SSH,否则界面上的报错信息往往不如终端里直观。
5.6 常见问题速查表格
| 现象 | 大概率原因 | 快速处理 |
|---|---|---|
Permission denied (publickey) | 私钥权限不对、未加入 agent、公钥未上传 | 修正 600/700 权限,ssh-add,检查 GitHub 网页密钥 |
Connection timed out | 22 端口被限制 | 尝试ssh.github.com:443的 SSH over 443 方案 |
Repository not found | 没有权限访问该仓库 | 检查登录账号是否正确,确认是否被移除为协作者 |
| 推送时反复要输密码 | credential helper 未配置 | 执行gh auth setup-git |
Failed to add SSH host key | known_hosts锁定导致 | 清掉对应条目或删除~/.ssh/known_hosts重新连接 |
| 新密钥不生效 | Windows 下未刷新 agent 缓存 | 重启终端或执行ssh-add重新加载密钥 |
这张表不能覆盖所有情况,但 80% 的新手问题都落在这几类里,足够应付日常开发了。
最后再分享一点个人体会:我是从去年开始彻底把 GitHub 侧认证切到gh的。当时搞完最大的感受不是“少输了几次密码”,而是整个人的心智负担减轻了。以前每次给新环境配代码仓库,都要调动“生成密钥、上传、配置 host、加 agent”这一整套知识,现在只要一句gh auth login,系统就帮着把后面的事全部搞定,剩下的精力可以真正花在写代码上。如果你也被 SSH 配置折腾过,不妨找个下午,把新电脑或者一台不常用的机器拿来试一次gh auth login,对比一下旧流程的体验差异。