最近在 Fork 这个 Git 图形客户端里拉取代码时遇到一个问题:远程仓库地址看起来没错,终端里也能改 Git 配置,但 Fork 里 fetch 或 pull 还是失败,报错里出现了 CRYPT_E_REVOCATION_OFFLINE。
最后解决方式反而很简单:把 Fork 里的 Git executable / Git instance 改成系统里正在用的 Git。改完之后,之前执行过的 Git 全局配置才真正被 Fork 读取到。
这篇记录一下这个问题的原因和排查顺序。
报错是什么意思
CRYPT_E_REVOCATION_OFFLINE 通常和 Git 的 HTTPS 证书检查有关,常见报错大概类似:
schannel: next InitializeSecurityContext failed:
CRYPT_E_REVOCATION_OFFLINE
The revocation function was unable to check revocation because the revocation server was offline.
它的意思不是“仓库不存在”,也不是“remote 地址一定错了”,而是 Git 在通过 HTTPS 访问远程仓库时,系统尝试检查证书吊销状态,但是访问不到吊销检查服务器。
在 Windows / Git for Windows 环境里,这个问题常和 Schannel、代理、防火墙、公司网络、证书吊销检查有关。
先不要急着改 remote
遇到拉取失败时,第一步还是先确认 remote:
git remote -v
git fetch origin
如果 remote 地址错了,比如 origin 指向了不存在的仓库,那当然要先改:
git remote set-url origin https://github.com/用户名/仓库名.git
但如果 remote 没错,错误里明确出现 CRYPT_E_REVOCATION_OFFLINE,重点就应该转向证书检查、代理和 Fork 使用的 Git 实例。
常见修复命令
网上最常见的修复方式是关闭 Schannel 的证书吊销在线检查:
git config --global http.schannelCheckRevoke false
这个命令执行成功时通常不会有任何提示,这是正常的。可以这样确认配置是否写入:
git config --global --get http.schannelCheckRevoke
git config --show-origin --get-all http.schannelCheckRevoke
如果输出是:
false
说明当前终端使用的 Git 已经读到了这个配置。
这里要注意,它和下面这个命令不是一回事:
git config --global http.sslVerify false
不建议随便关闭 sslVerify。http.schannelCheckRevoke false 只是关闭 Schannel 的证书吊销在线检查,范围更小;而 http.sslVerify false 会直接关闭 HTTPS 证书校验,风险更高。
为什么在终端配置了,Fork 还是不好使
关键点在这里:Fork 不一定使用你终端里的那个 Git。
Fork 可能使用:
- 自带的内置 Git。
- 系统安装的 Git。
- Git for Windows 的某个 Git。
- 你通过其他工具安装的另一个 Git。
如果你在终端里执行:
git config --global http.schannelCheckRevoke false
这个配置只保证对“当前终端正在调用的 Git”生效。Fork 如果使用的是另一个 Git 实例,它可能读不到这套全局配置。
所以会出现一种很迷惑的现象:
- 终端里
git fetch可以。 - Fork 里 fetch / pull 还是失败。
- Git 全局配置看起来也已经写了。
这时不要继续乱改 remote,应该去 Fork 里检查 Git executable。
最终解决:让 Fork 使用系统 Git
在 Fork 里打开设置:
Fork -> Preferences / Settings -> Git
找到类似下面的选项:
Git executable
Git instance
Git path
把它改成你系统里正在使用的 Git。
在 Windows 终端里可以先查当前 Git 路径:
where git
git --version
在 macOS / Linux 里可以查:
which git
git --version
然后在 Fork 里选择同一个 Git。保存后重新打开仓库,再执行 fetch / pull。
这次问题就是这样解决的:不是 remote 配错,也不是 git config 命令没生效,而是 Fork 之前用的 Git 和终端里配置的 Git 不是同一个。
还可以用本地配置兜底
如果不确定 Fork 是否读取全局配置,也可以在具体项目目录里写一份 local 配置:
cd 你的项目目录
git config --local http.schannelCheckRevoke false
git config --local --get http.schannelCheckRevoke
local 配置会写到当前仓库的 .git/config 里,只影响这个仓库。它不如统一 Git executable 根治,但排查时可以作为临时兜底。
代理也要顺手检查
如果处在公司网络、代理网络或访问 GitHub 不稳定的环境里,还要检查 Git 的代理配置:
git config --global --get http.proxy
git config --global --get https.proxy
需要代理时可以设置:
git config --global http.proxy http://127.0.0.1:端口
git config --global https.proxy http://127.0.0.1:端口
不需要代理时可以清掉:
git config --global --unset http.proxy
git config --global --unset https.proxy
不过如果终端能拉、Fork 不能拉,优先还是看 Fork 使用的是不是同一个 Git。
如果不想碰 HTTPS,可以改 SSH
CRYPT_E_REVOCATION_OFFLINE 多发生在 HTTPS 访问远程仓库时。如果 HTTPS 证书链或代理环境一直折腾,也可以把 remote 改成 SSH:
git remote -v
git remote set-url origin [email protected]:用户名/仓库名.git
git fetch origin
如果 SSH 的 22 端口被网络拦截,还可以配置 GitHub SSH 走 443 端口。这个属于另一个问题,但思路是绕开 HTTPS 证书吊销检查这一层。
排查顺序
我现在会按这个顺序看:
- 先看
git remote -v,确认远程地址没有写错。 - 在终端执行
git fetch origin,看终端是否也报错。 - 如果报
CRYPT_E_REVOCATION_OFFLINE,执行git config --global http.schannelCheckRevoke false。 - 用
git config --show-origin --get-all http.schannelCheckRevoke确认配置来源。 - 如果终端正常但 Fork 不正常,去 Fork 设置里改
Git executable/Git instance。 - 仍然失败,再检查代理、账号权限、SSH key 或 remote 协议。
结论
这次问题的关键不是 Git remote,而是 Fork 用的 Git 实例不对。
终端里设置了:
git config --global http.schannelCheckRevoke false
但 Fork 如果还在用内置 Git 或另一个 Git,它就可能读不到这条配置。把 Fork 的 Git executable / Git instance 改成系统正在用的 Git 之后,配置才统一,拉取代码也就恢复正常。
以后遇到“终端能拉,Fork 不能拉”的问题,可以优先记住一句话:先检查 Fork 用的是不是同一个 Git、同一个 SSH、同一个代理环境。