在将我的博客仓库从实验室主机迁移至宿舍笔记本的过程中,遇见的Git与hexo相关的小问题的记录,存在一些基础的小问题,真是被自己蠢到了。
一、迁移目标
原博客管理方式
- master分支管理静态网页(public)
- source分支管理相关资源
foo1s.github.io
│
├── master
│ └── Hexo 生成后的静态网页(public)
│
└── source
├── source/
├── themes/
├── package.json
├── _config.yml
└── Hexo 博客源码
迁移操作
安装环境
↓
clone source 分支
↓
npm install
↓
hexo g
↓
hexo d
二、问题一——GitHub 下载很慢
问题现象
在新电脑上执行:
git clone https://github.com/foo1s/foo1s.github.io.git
下载到一半失败,并出现如下错误:
error: RPC failed; curl 92 HTTP/2 stream 5 was not closed cleanlyfatal: early EOFfatal: fetch-pack: invalid index-pack output
虽然 Git 已经连接到 GitHub,并开始下载对象,但数据传输过程中连接被中断,导致仓库无法完整克隆。
问题原因分析
刚开始容易误以为:
- GitHub 网络不好;
- Git 仓库损坏;
- Git 版本过低。
实际上都不是。
Git 在使用 HTTPS 克隆仓库时,其底层通信过程为:
Git
│
▼
libcurl
│
▼
HTTP/2
│
▼
V2Ray 本地代理
│
▼
GitHub
由于 Git 默认优先使用 HTTP/2,而部分 V2Ray/Xray 节点或代理软件对 HTTP/2 长连接、多路复用支持不够稳定,因此在大文件持续传输过程中容易发生连接中断。
于是 Git 收到的数据不完整,最终出现:
RPC failedearly EOFfetch-pack failed
本质上不是 Git 的 Bug,而是 HTTP/2 与代理之间的兼容性问题。
解决方案
将 Git 的 HTTP 协议版本强制切换为 HTTP/1.1:
git config --global http.version HTTP/1.1
重新执行:
git clone https://github.com/foo1s/foo1s.github.io.git
之后下载速度明显恢复正常,整个仓库能够顺利克隆。
为什么 HTTP/1.1 可以解决?
HTTP/2 的优势在于:
- 多路复用(Multiple Streams)
- 单连接同时传输多个请求
- 更高的理论性能
但是 Git Clone 实际上属于长时间、大数据量连续传输。
对于部分代理而言:
Git ↓HTTP/2 ↓代理
更容易出现:
- Stream Reset
- Stream Cancel
- Unexpected Disconnect
而 HTTP/1.1:
Git ↓HTTP/1.1 ↓代理
协议更加简单,兼容性更好,因此很多 GitHub 用户在使用代理时都会采用 HTTP/1.1。
本次收获
这次问题让我理解了 Git 网络通信的底层流程:
git clone
│
▼
Git
│
▼
libcurl(负责网络通信)
│
▼
HTTP/HTTPS 协议
│
▼
代理(V2Ray)
│
▼
GitHub
Git 本身并不直接负责网络传输,而是依赖底层网络库(libcurl)通过 HTTP/HTTPS 与 GitHub 通信。因此,当出现 RPC failed、early EOF 等错误时,并不一定是 Git 本身的问题,而应该从 网络环境、代理配置、HTTP 协议版本 等方面进行排查。
经验总结
以后如果再次遇到:
RPC failedHTTP/2 stream was not closed cleanlyearly EOFfetch-pack failed
可以优先检查以下几个方面:
网络或代理是否稳定;
是否正在使用 HTTP/2;
尝试切换为 HTTP/1.1:
git config --global http.version HTTP/1.1如果使用代理,确认 Git 是否正确走代理,以及代理节点质量是否正常。
三、问题二——SSH Key
原来认为是不是Git 用户名一样和Git 邮箱一样应该就可以push代码了(有点蠢好久没用了)
实际上,Git 用户名:
git config user.name
只是知道commit 作者是谁。根本不是身份认证。真正认证的是:
SSH Key
也就是:
id_ed25519
id_ed25519.pub
四、问题三——SSH Key 为什么认证错账号?
一个 GitHub 账号可以绑定多把不同的 SSH Key(每台设备一把,推荐做法)。
一把 SSH Key不能同时绑定到多个 GitHub 账号。
一台电脑可以保存多把 SSH Key**,并通过~/.ssh/config为不同账号或仓库指定使用哪一把。
如何打开~/.ssh/config
Vscode
code ~/.ssh/config
记事本
notepad ~/.ssh/config
Host github.com必须顶格写。- 下面四行前面建议保留 4 个空格(Tab 或空格都可以,但统一即可)。
- 放在整个文件最前面,不要放到最后。
git会按顺序匹配SSH key
按顺序尝试,只要成功,后面的 Key 就不会再尝试。
你有两套 SSH Key, ‘id_rsa’和’id_ed25519’,分别指向’Huaweizhou’和’foo1s’
ssh -T git@github.com
一直返回:
Hi Huaweizhou!
后来:
ssh -vT git@github.com //查看github绑定的SSH key
ssh -i ~/.ssh/id_ed25519 -T git@github.com //查看SSH key服务的github账号
终于发现:
Offering public key:
id_rsa
GitHub 第一把 Key 就认证成功了。
所以:
id_ed25519
根本没有机会发送。
五、问题四——为什么 hexo d 可以,git push 不可以?
问题现象
博客能够正常执行:
hexo d
成功部署到 master 分支。
但是在 source 分支执行:
git push origin source
却提示:
remote: Invalid username or token.Password authentication is not supported for Git operations.fatal: Authentication failed
一开始认为:
都是向同一个 GitHub 仓库推送代码,为什么一个成功,一个失败?
问题原因分析
经过排查发现,虽然目标仓库相同,但使用的是两种完全不同的通信协议和认证方式。
① hexo d 使用的是 SSH
Hexo 的部署配置(_config.yml)中:
deploy: type: git repo: git@github.com:foo1s/foo1s.github.io.git branch: master
部署流程为:
hexo d
│
▼
git@github.com
│
▼
SSH 协议
│
▼
SSH Key(id_ed25519)
│
▼
GitHub 身份认证
由于前面已经正确配置了 SSH Key,因此部署成功。
② git push 使用的是 HTTPS
查看远程仓库:
git remote -v
得到:
origin https://github.com/foo1s/foo1s.github.io.git
此时 Git 的通信流程变成:
git push
│
▼
https://github.com
│
▼
HTTPS 协议
│
▼
Git Credential Manager
│
▼
用户名 / Personal Access Token
HTTPS 并不会使用 SSH Key,而是依赖 Git Credential Manager 保存的账号信息或 Personal Access Token(PAT)进行认证。
由于电脑中保存的是旧账号或无效 Token,因此 GitHub 返回认证失败:
Invalid username or token.
解决方案
将远程仓库统一修改为 SSH 地址:
git remote set-url origin git@github.com:foo1s/foo1s.github.io.git
再次查看:
git remote -v
确认变为:
origin git@github.com:foo1s/foo1s.github.io.git
之后执行:
git push origin source
即可正常推送。
本次收获
这次问题让我真正理解了 Git 的两种远程访问方式:
| 对比项 | SSH | HTTPS |
|---|---|---|
| 远程地址 | git@github.com:... |
https://github.com/... |
| 认证方式 | SSH Key | 用户名 + Personal Access Token(PAT)或 Git Credential Manager |
是否使用 ~/.ssh |
✅ 是 | ❌ 否 |
| 是否受 SSH Key 配置影响 | ✅ 是 | ❌ 否 |
虽然两种方式最终访问的是同一个 GitHub 仓库,但它们的认证机制完全独立。
经验总结
以后排查 GitHub 推送失败时,应首先确认使用的是哪种协议:
git remote -v
- 如果是 **
git@github.com**,优先检查 SSH Key、~/.ssh/config、ssh -T git@github.com等配置。 - 如果是 **
https://github.com**,则需要检查 Git Credential Manager 中保存的账号信息或 Personal Access Token 是否正确。
为了避免不同协议带来的认证问题,建议整个 Hexo 博客工作流统一使用 SSH:
- 克隆源码:
git clone git@github.com:... - 推送源码:
git push origin source - 部署博客:
hexo d
统一使用 SSH 后,只需维护一套 SSH Key,既减少了认证问题,也使整个博客维护流程更加一致和稳定。
六、问题五——为什么 Git Push 会提示 Username or Token?
问题现象
执行:
git push origin source
Git 返回:
remote: Invalid username or token.Password authentication is not supported for Git operations.fatal: Authentication failed
一开始误以为:
- Git 配置错误;
- GitHub 仓库权限异常;
- 用户名或密码输入错误。
实际上都不是。
问题原因分析
GitHub 自 2021 年 8 月 起,正式停止支持使用 GitHub 账号密码 进行 Git 操作认证。
也就是说,HTTPS 方式访问 GitHub 时:
https://github.com
已经不能使用:
用户名 + GitHub 登录密码
进行认证。
现在 HTTPS 认证主要依赖:
- Personal Access Token(PAT)
- Git Credential Manager(内部保存 PAT)
整个认证流程如下:
git push
│
▼
HTTPS
│
▼
Git Credential Manager
│
▼
Personal Access Token(PAT)
│
▼
GitHub
如果:
- Token 已过期;
- Token 权限不足;
- 保存的是旧账号的 Token;
- 本地没有 Token;
GitHub 就会拒绝认证,并返回:
Invalid username or token.
因此,这个错误并不是 Git 出现故障,而是 HTTPS 身份认证失败。
解决方案
本次迁移最终没有继续使用 HTTPS,而是统一改为 SSH。
修改远程仓库地址:
git remote set-url origin git@github.com:foo1s/foo1s.github.io.git
之后 Git 的认证流程变为:
git push
│
▼
SSH
│
▼
SSH Key
│
▼
GitHub
无需再维护 Personal Access Token,也无需每次输入用户名或密码。
本次收获
这次问题让我了解到:
- GitHub 已经不再支持账号密码进行 Git 操作认证。
- HTTPS 与 SSH 是两套完全不同的认证体系。
- 使用 HTTPS 时,本质上依赖的是 Personal Access Token,而不是登录密码。
- Git Credential Manager 只是帮助本地保存和管理 Token,并不是另一种认证方式。
经验总结
以后如果遇到:
Invalid username or token.Authentication failed.Password authentication is not supported for Git operations.
应首先判断当前是否使用的是 HTTPS:
git remote -v
如果远程地址为:
https://github.com/...
则说明问题很可能出现在 Token 或 Git Credential Manager。
如果远程地址为:
git@github.com:...
则应排查 SSH Key、SSH 配置以及 GitHub SSH 权限。
对于个人博客、个人项目等长期维护的仓库,优先采用 SSH 方式进行 Git 操作更加方便和稳定,可以避免 Token 管理、过期更新等额外维护成本。
七、知识体系
GitHub Repository
│
┌─────────────┴─────────────┐
│ │
source master
源码 静态网页
│ │
│ git push │ hexo d
│ │
└─────────────┬─────────────┘
│
Git
│
SSH / HTTPS 两种协议
│ │
SSH Key Token/Credential
│ │
id_ed25519 Git Credential Manager
八、迁移 Hexo 博客完整流程
以后拿到一台新电脑,你应该能够独立完成:
安装 Git
安装 Node.js
安装 Hexo CLI(如果没有)
配置 Git 用户名、邮箱
配置 SSH Key,并确认:
ssh -T git@github.com返回的是正确账号。
用 SSH 地址克隆
source分支:git clone -b source git@github.com:foo1s/foo1s.github.io.git执行:
npm install本地预览:
hexo clean hexo g hexo s推送源码:
git push origin source部署博客:
hexo d
迁移总结
- Git 提交身份(user.name / user.email) 与 GitHub 身份认证(SSH Key / Token) 是两套独立机制。
- SSH 与 HTTPS 是两种完全不同的 Git 传输协议,认证方式也完全不同。
- 一台电脑可以拥有多把 SSH Key、一个 GitHub 账号也可以绑定多把 SSH Key;真正决定使用哪一把的是 SSH 的配置和选择逻辑。
hexo d本质上是对 Git 的封装,排查 Hexo 部署问题时,最终还是要回到 Git 的配置和认证上。