博客仓库迁移问题小记


在将我的博客仓库从实验室主机迁移至宿舍笔记本的过程中,遇见的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

可以优先检查以下几个方面:

  1. 网络或代理是否稳定;

  2. 是否正在使用 HTTP/2;

  3. 尝试切换为 HTTP/1.1:

    git config --global http.version HTTP/1.1
    
  4. 如果使用代理,确认 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,也无需每次输入用户名或密码。


本次收获

这次问题让我了解到:

  1. GitHub 已经不再支持账号密码进行 Git 操作认证。
  2. HTTPS 与 SSH 是两套完全不同的认证体系。
  3. 使用 HTTPS 时,本质上依赖的是 Personal Access Token,而不是登录密码。
  4. 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 博客完整流程

以后拿到一台新电脑,你应该能够独立完成:

  1. 安装 Git

  2. 安装 Node.js

  3. 安装 Hexo CLI(如果没有)

  4. 配置 Git 用户名、邮箱

  5. 配置 SSH Key,并确认:

    ssh -T git@github.com
    

    返回的是正确账号。

  6. 用 SSH 地址克隆 source 分支:

    git clone -b source git@github.com:foo1s/foo1s.github.io.git
    
  7. 执行:

    npm install
    
  8. 本地预览:

    hexo clean
    hexo g
    hexo s
    
  9. 推送源码:

    git push origin source
    
  10. 部署博客:

    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 的配置和认证上。

评论