当前位置: 首页 > news >正文

能连上 GitHub(SSH 验证成功),却 push 失败?常见原因与逐步解决方案 - 详解

能连上 GitHub(SSH 验证成功),却 push 失败?常见原因与逐步解决方案 - 详解

能连上 GitHub(SSH 验证成功),却 push 失败?常见原因与逐步解决方案

在无法通过 HTTPS 或普通 Git 方式推送代码到远程仓库时,很多人会尝试改用 SSH 密钥的方式来连接与推送。本文先说明为什么网络策略或端口限制会导致无法 push、以及在什么场景下使用 SSH(尤其是将连接改为 ssh.github.com:443)可以绕过这些限制;随后分析为何有时即便 SSH 验证成功,git push 仍然失败,并给出可直接执行的解决方案与诊断命令,便于快速恢复推送能力。

一、为什么会出现“能连上但无法 push”的矛盾?

在继续分析具体原因之前,先简要说明“为什么有时改用 SSH 密钥可以绕过网络限制”:

  1. 网络端口与代理策略差异
    • 许多公司封锁外部 22 端口,允许 443(HTTPS)。通过把 ssh 目标指向 ssh.github.com:443 可以通过防火墙,但这需要 SSH 客户端实际使用该端口。
  2. SSH 验证成功只是说明公钥在 GitHub 上被接受,但 git push 失败可能是因为:
    • Git 在执行 push 时没有使用你测试时用的同一把私钥(例如你用 ssh -i 测试成功,但 git 调用的 ssh 没有读取该 key)。
    • Git 调用了不同的 ssh 可执行文件(系统自带的、Git for Windows 自带的或 Putty/plink),而这些客户端对 ~/.ssh/config 或端口声明的支持不同。
    • remote URL 使用了 ssh://...:443 这类带端口的写法时,有的 Git 的 ssh 变体(“simple”)不支持在 URL 中带端口,会报 “ssh variant ‘simple’ does not support setting port”。
    • ssh-agent 未加载或私钥权限不当,导致 push 时没有合适的私钥被提供给远端(即使单次 ssh -i 可用)。
  3. 本地路径/配置格式不兼容(Windows 路径在 Git Bash 下需用 POSIX 形式),导致 Git 调用 ssh 时失败或不读取 config

结论:ssh 验证成功说明“密钥对 + GitHub”是正确的;失败通常出在“git 调用 ssh 的方式”或“remote URL 与客户端组合”的不匹配上。


二、优先的检查与调试命令(先执行这些,便于定位)

在能访问命令行的机器上按顺序执行(把输出保存/粘贴用于进一步分析):

  • 验证 SSH 单次连接(指定私钥和端口)

    • Git Bash:
      ssh -i /c/Users/youruser/.ssh/id_ed25519_project -T -p 443 git@ssh.github.com
    • PowerShell:
      ssh -i C:\Users\youruser\.ssh\id_ed25519_project -T -p 443 git@ssh.github.com
  • 查看尝试密钥的详细信息(verbose)

    ssh -vvv -i /c/Users/youruser/.ssh/id_ed25519_project -T -p 443 git@ssh.github.com
  • 检查 Git 用哪个 ssh(可能为空)

    git config --get core.sshCommand
    git config --global --get core.sshCommand
    git var GIT_SSH
    where.exe ssh
  • 查看远程 URL 与当前 remote

    git remote -v
  • 在 push 时用 verbose 查看 ssh 行为(临时,不持久)

    # Git Bash 临时
    export GIT_SSH_COMMAND="ssh -vvv -F /c/Users/youruser/.ssh/config"
    git push origin master
    unset GIT_SSH_COMMAND
    # PowerShell 临时
    $env:GIT_SSH_COMMAND = "ssh -vvv -F C:\Users\youruser\.ssh\config"
    git push origin master
    Remove-Item Env:\GIT_SSH_COMMAND

三、逐条可执行方案(按便利性/长期性排序)

方案 1 — 推荐:在 ~/.ssh/config 映射 host(一次配置,透明生效)

  • C:\Users\<user>\.ssh\config 写:
    Host github.comHostName ssh.github.comPort 443User gitIdentityFile C:/Users/youruser/.ssh/id_ed25519_projectIdentitiesOnly yes
  • 优点:你可以继续使用 git@github.com:OWNER/REPO.git 形式的 remote,SSH 会透明走 443 并用指定 key,适合大量仓库。

方案 2 — 推荐备选:在当前会话临时指定 ssh(立刻生效,适合不想改配置时)

  • Git Bash:
    export GIT_SSH_COMMAND="/c/Windows/System32/OpenSSH/ssh.exe -F /c/Users/youruser/.ssh/config"
    git push origin master
    unset GIT_SSH_COMMAND
  • PowerShell:
    $env:GIT_SSH_COMMAND='C:\Windows\System32\OpenSSH\ssh.exe -F C:\Users\youruser\.ssh\config'
    git push origin master
    Remove-Item Env:\GIT_SSH_COMMAND
  • 优点:无需改全局设置或每个仓库,适合临时使用或测试。

方案 3 — 持久化:让 Git 永久使用指定 OpenSSH(写入 core.sshCommand)

  • 在 Git Bash(或 PowerShell)执行:
    git config --global core.sshCommand "/c/Windows/System32/OpenSSH/ssh.exe -F /c/Users/youruser/.ssh/config"
  • 优点:一次配置后所有仓库自动使用该 ssh 客户端,适合你最终希望长期生效的场景。

方案 4 — 把 remote 改成不带端口的 SSH(仅当前仓库)

  • 在仓库目录执行:
    git remote set-url origin git@github.com:OWNER/REPO.git
    git push origin master
  • 说明:如果方案 1 的 ~/.ssh/config 已正确设置,这种写法会通过 config 映射到 ssh.github.com:443。适合逐仓切换的做法。

方案 5 — 全局 URL 重写(大量仓库且 remote 多为 HTTPS)

  • https://github.com/... 自动走 ssh://git@ssh.github.com:443/...
    git config --global url."ssh://git@ssh.github.com:443/".insteadOf "https://github.com/"
  • 优点:不需改每个仓库的 remote,适合公司内大量已有 HTTPS remote 的情形。

方案 6 — 离线/替代推送(当所有外网被限制)

  • 使用 git bundle 在内网打包,然后在能上网的机器上 clone/bundle 并 push:
    # 内网机器
    git bundle create ../repo.bundle --all
    # 在能上网的机器上
    git clone repo.bundle repo-from-bundle
    cd repo-from-bundle
    git remote add origin https://github.com/OWNER/REPO.git
    git push origin --all
    git push origin --tags

四、常见错误与针对性修复

  • 错误 “ssh variant ‘simple’ does not support setting port”

    • 原因:remote 使用了 ssh://...:PORT 形式,但 Git 内置 ssh 变体不支持 URL 里显式端口。
    • 解决:去掉 URL 中的端口,改用 git@github.com:owner/repo.git 并依赖 ~/.ssh/config 做端口映射,或设置 core.sshCommand 强制使用系统 OpenSSH。
  • 报 “Permission denied (publickey).” 在 push 时,但 ssh -i ... 验证成功

    • 原因:git push 调用了不同的 ssh(或未加载该私钥),或者 ssh 在 push 时未读取你的 config
    • 解决:用 GIT_SSH_COMMAND 指定同一 ssh 可执行文件或在 ~/.ssh/config 中声明 IdentityFile;也可把私钥放到默认位置并用 ssh-agent 加载。
  • 在 Windows 下设置 core.sshCommand 出现 “command not found” 或路径问题

    • 原因:Git Bash 解释 Windows 路径不兼容(需要 POSIX 路径 /c/Windows/…)。
    • 解决:在 Git Bash 使用 /c/Windows/System32/OpenSSH/ssh.exe 形式;在 PowerShell 使用双反斜杠转义路径。

五、安全与运维建议


六、快速决策指南(选择一个最快恢复办法)

  • 想最快解决并不改任何仓库:在当前终端临时执行 GIT_SSH_COMMAND(方案 2)。
  • 想一次性对所有仓库透明生效:写 ~/.ssh/config 并把 remote 保持 git@github.com:...(方案 1)。
  • 仓库多且为 HTTPS:使用全局 insteadOf 自动重写(方案 5)。
  • 完全无外网访问:使用 git bundle 离线转发(方案 6)。
http://www.hskmm.com/?act=detail&tid=29152

相关文章:

  • 换根dp的一个trick
  • 搭建SSH服务于RK3399平台上的Ubuntu 18.04,实现远程连接
  • 深入探讨MySQL的二进制日志(binlog)选项
  • sparkml 多列共享labelEncoder - 详解
  • 一键解决MetaHuman播放动画时头部穿模问题
  • 忽然很好奇为什么素未谋面的大家都知道我是学姐?
  • UE网络编程完全指南:UDP TCP WebSocket实现详解
  • 配置Nginx服务器在Ubuntu平台上
  • 缓存一致性验证秘笈
  • 从十五岁的今天写给十六岁的明天
  • kali U盘启动持久化
  • 深入解析:Telerik UI for ASP.NET MVC 2025 Q3
  • Java依记 DAY02 - I
  • 元推理:汉字的发音,同音也是某种同构?
  • 题解:qoj7759 Permutation Counting 2
  • WAV 转 flac 格式
  • EtherCAT芯片没有倍福授权的风险
  • 为何是「对话式」智能体?因为人类本能丨对话式智能体专场,Convo AIRTE2025
  • 2014-2024高考真题考点分布详细分析(另附完整高考真题下载) - 详解
  • P4147 玉蟾宫(最大子矩形)
  • 2025 年 10 月西安房屋鉴定公司最新推荐排行榜:覆盖房屋安全评估、结构检测、承载力鉴定、危房鉴定领域,助您选专业机构
  • 完整教程:HAProxy 完整指南:简介、负载均衡原理与安装配置
  • K
  • 阿里发布「夸克 AI 眼镜」:融合阿里购物、地图、支付生态;苹果拟收购计算机视觉初创 Prompt AI丨日报
  • 在AI技术唾手可得的时代,挖掘新需求成为制胜关键——某知名AI聊天框架需求探索
  • 数论学习之路
  • 生成式AI实现多模态信息检索技术突破
  • 在运维工作中,如何过滤某个目录在那边什么路径下面?
  • 完整教程:安卓中,kotlin如何写app界面?
  • 移动固态硬盘插入电脑后提示“应该格式化”或“文件系统损坏”如何修复?