上一篇把 Hexo 的发布方式改成了:源码统一放在私有的 blog-source,GitHub Actions 负责生成网页,再自动更新 guohuahu.github.io。这样以后,电脑、手机或者 ChatGPT 都可以作为博客的编辑入口。
新的问题也随之出现了。以前博客源码只在自己的电脑上,本地就是唯一版本;现在 ChatGPT 也可能直接修改 GitHub 上的源码,手机端以后也可能这么做。那么下一次回到电脑继续写的时候,本地仓库就不一定是最新的。正常的 Git 使用习惯当然是先 pull 再 push,但对于博客源码,我觉得还应该多考虑一步:假如远程仓库本身出了问题,直接 pull 回来,会不会把本地正常的文章一起弄坏?
为什么不能直接pull
最常见的做法大概是:
1 | git pull |
如果远程只是正常多了一篇文章,这样没有问题。但现在远程仓库已经不只由本地电脑修改。比如我可以直接让 ChatGPT 在 GitHub 上新增文章、改配置,GitHub Actions 也会根据这些源码继续发布。下一次打开本地仓库的时候,本地和远程出现差异已经是正常情况,而不是异常情况。
问题在于,pull 会直接影响当前工作区。假如远程因为误操作删掉了大量文章,或者某次提交把整个 source/ 弄坏了,本地一上来就 pull,相当于把最后一份正常副本也跟着改掉。Git 虽然有历史可以恢复,但真到了出问题的时候,再去翻 reflog、找 commit,还是比较麻烦。
所以我给本地增加了一层比较保守的同步流程:
1 | 本地准备 push |
先给source留一份副本
每次同步以前,先把整个 source/ 复制到 Git 仓库之外,而且包括还没有加入 Git 的文件。备份目录按时间保存,例如:
1 | ../.hexo-source-backups/Blog/20261002-032500/source/ |
这样做有点笨,但是很有用。Markdown 本身并不大,几十篇文章和一些页面占不了多少空间,完全没有必要为了省这一点空间承担风险。即使后面的 Git 操作真的出了问题,至少文章原文件还在。
这里特意把备份放到仓库外面,也是为了避免备份文件自己又被 Git 跟踪,最后跟着源码一起上传。
fetch以后先看看远程发生了什么
第二步也不是 git pull,而是先:
1 | git fetch --prune |
fetch 只更新远程分支信息,不会改当前工作区。这样就可以先比较本地和远程共同祖先到远程最新版本之间,source/ 到底发生了哪些变化。
脚本会统计:
1 | 新增了多少文件 |
如果只是 ChatGPT 在远程增加了一篇文章,或者改了少量 Markdown,就继续。如果发现远程的 source/ 整个消失,或者删除数量明显异常,就直接停止,不往本地合并。
我现在设的判断比较保守:远程一次删除至少 10 个文件,并且超过原有 source/ 文件数的 30%,就认为值得人工检查。这个数字当然不是通用标准,只是给自己的博客加一道保险。真正重要的不是 10 或 30%,而是 pull 以前先判断“远程这次改动像不像正常编辑”。
本地和远程都有修改怎么办
检查通过以后,再根据两边的状态决定怎么同步。如果本地没有新提交,只是落后于远程,就使用 fast-forward;如果本地和远程都各自有新提交,就 rebase 到远程最新版本。假如 rebase 出现冲突,脚本会自动 abort,恢复到操作以前的状态,再让人自己处理。
整个过程不使用:
1 | git reset --hard |
最后仍然只是普通的 git push。因为对于博客源码来说,我更愿意让同步失败,也不愿意为了“自动成功”去强行覆盖某一边。
另外,如果本地已经有修改但还没有 commit,也不会继续自动同步。先把自己正在写的东西处理清楚,再碰远程版本,比较容易知道冲突到底来自哪里。
和自动发布接起来
这样以后,博客大概有两条入口:
1 | 电脑本地 |
另一条则是:
1 | 手机 / ChatGPT |
云端修改以后,本地下一次提交会先看到这些变化;本地修改以后,推送到源码仓库又会自动触发网站构建。这样两个入口可以同时存在,但都围绕同一个 blog-source 工作。
以前本地电脑既保存源码,又负责生成和部署,所以很少考虑“远程版本会不会比本地新”。现在发布已经搬到云端,ChatGPT 也可以直接修改源码,这个问题反而必须认真处理。自动化越多,越不能简单地把所有命令连起来就算完成,最好给重要的数据留一个可以停下来的地方。
对我来说,博客最重要的还是 source/ 里面这些 Markdown。网页坏了可以重新生成,Actions 配错了可以再改,甚至整个 guohuahu.github.io 都可以重新部署,但是文章本身没必要跟着这些自动化一起冒险。先备份,再检查,再同步,虽然多了几步,反而更适合现在这种本地和云端都可能修改源码的方式。