博客内容分离到私有仓库,构建时自动同步
博客用的是 Firefly,fork 之后改了不少东西,想着把主题仓库开源出来。但仓库里的 src/content 装的是文章、动态、足迹、项目介绍,这些是要自己留着的。
一开始想的是清历史,用 filter-repo 把 content 从所有提交里抹掉。动手前先摸了下底,发现代价比想象中大:Firefly 上游的第一个提交就带着 content 目录,要清掉它就得改写根提交,接着全部提交的 SHA 都会变,之后再也无法和上游 merge。而且清历史也不等于内容消失了,远端 force push 之后,旧的提交在一段时间内还是能通过 SHA 访问到。
于是换了个思路:内容搬走,主仓库只留代码。
结构
- 私有仓库
my-blog-content,目录结构原样镜像src/content/* - 主仓库
.gitignore里加一行src/content/ package.json的dev和build第一步都跑node scripts/sync-content.mjs
本地开发时,src/content 就是那个私有仓库的工作副本,写文章、提交都在它自己的 git 里完成,主仓库全程不掺和。
同步脚本的取舍
脚本要处理的情况只有几种,但每一种都有伤到数据的可能,所以原则定得比较死:宁可什么都不做,也不动你的文件。
src/content 状态 | 行为 |
|---|---|
| 不存在 | clone 内容仓库 |
| 是工作副本且没有未提交改动 | git pull --ff-only |
| 有未提交改动 | 跳过更新,保留工作副本 |
| 存在但不是 git 仓库 | 默认不动(加 --force 才改名备份后重新克隆) |
| 拉取失败但本地有内容 | 打警告,继续用现有的 |
| 拉取失败且本地没有内容 | 中止构建 |
最后一条是刻意加的。构建平台拉不到内容时如果不中止,就会部署出一个没有文章的站点,这比构建失败更难发现。
两个踩到的坑
浅克隆会让更新永久失效
内容仓库很小,一开始想着用 --depth 1 省点时间,同步时 git fetch --depth 1 再 git merge --ff-only FETCH_HEAD。
结果是永远更新不了,git 报历史不相干。原因是浅克隆拿到的是一棵孤立的树,fetch 回来的又是另一棵,两者没有共同祖先,--ff-only 直接判定不可快进。改成全量克隆就好了,反正仓库里只有几十个文本文件。
|| true 会吞掉它前面整段的失败
原来的构建链是这种写法:
... && npx tsx scripts/build-hitokoto.ts || true && npx tsx scripts/...|| true 绑定的是它前面那条完整的链。我把内容同步放到构建链最前面之后,同步失败也照样返回 0,构建继续往下跑,最后部署出去一个空站。
改成用括号把可选步骤圈起来:
node scripts/sync-content.mjs && (node scripts/sync-friends.mjs && npx tsx ... || true) && ...同步这一步失败就会老实中断。
把 content 移出索引
工作区里的文件要留着(还要继续写文章),但主仓库不能再跟踪这个目录。
常规做法是 git rm -r --cached src/content,只是我这边的 git 工作区是映射进来的目录,之前有被 git rm 连磁盘文件一起清掉的经历,不太敢再用它。换成只动索引的写法:
git ls-files -z -- src/content | git update-index --force-remove -z --stdin跑完 git status 会看到那批文件显示成 D,但磁盘上一个都没少。提交之后,主仓库就彻底不跟踪 src/content 了。
内容推送了,站点却不更新
这个问题比较隐蔽。EdgeOne 的 Git 自动部署只监听主仓库,内容仓库推文章它完全不知道。表现就是文章推上去了,本地 dev 能看到,线上还是旧的。
办法是在内容仓库加一个 workflow,push 到 main 时主动打一次 EdgeOne 的部署钩子。几个细节:
- 钩子是 POST 触发,URL 本身就带认证,不需要额外 header 或者 body,带不带都能正常返回
- 加了
concurrency配置,连着推几篇只触发一次部署,不会排队构建好几遍 - 钩子 URL 放在仓库 Secret 里。没配的时候 workflow 只打一行 warning 就跳过,这样不会天天红叉,但也得记得配,否则就是静默失效
剩下的事
内容分离之后,有几处还指着老路径。写博客的机器人之前是往主仓库的 src/content/posts 推文章的,现在得改成指向内容仓库。
支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!











