静态博客隐藏着一个容易被人忽略的隐私问题,我也是刚刚遇到。

关于静态博客的搭建环境:如果你是依赖git和github的仓库进行部署的静态博客,极有可能会遇到这种情况。

如果你发表了一篇博文,已经提交github并且在服务器部署成功,这个时候你又后悔了,不想让任何人看到这篇文章,这个时候,你会选择本地删除这篇博文,然后提交新的版本,部署成功后,该博客不在显示该博文。

如果你想让这篇博文在互联网上物理消失,这么做绝对是不行的!

问题的根源是 Git,不是静态博客生成器。 任何用 Git 管理内容的博客(Astro、Hugo、Jekyll、Hexo 等),文件一旦被 git push 到远端,要彻底抹掉都得走这套流程。

具体来说,看你的文章在什么阶段,对应的方法也不同。

以下内容均为大模型编写,请谨慎使用下文的命令


几种删除方法

还没提交 git add 了

还在工作区,直接删除文件就行,连 git 操作都不需要。

已提交但还没 push

最简单的就是 git commit --amend 修改上一次提交,把不需要的文件从提交中移除。或者 git reset HEAD~1 撤销提交,删掉文件后重新 commit。

刚 push 不久,只有一次提交

git rebase -i 把包含目标文件的 commit 删掉或 squash 掉,然后 git push origin master --force。一步到位,不需要 filter-branch 那么重的操作。

文件已经产生多次提交,且推送到远端很久了

这时候就需要重写历史:

# 方案一(推荐,需安装 git-filter-repo)
pip3 install git-filter-repo
git filter-repo --path src/content/blog/xxx.md --invert-paths

# 方案二(传统方式,git 自带)
git filter-branch --force --index-filter \
  'git rm --cached --ignore-unmatch "path/to/file"' \
  --prune-empty --tag-name-filter cat -- --all

完事后还要清理本地残留数据:

git reflog expire --expire=now --all
git gc --prune=now --aggressive
git push origin master --force

之所以这么繁琐,是因为 Git 的设计理念就是”不丢数据”,每一次提交都是不可变的快照。你后来的”删除”只是在最新快照中去掉了文件,但之前的所有快照都还在仓库里,不重写历史就永远不会消失。


几个避免以后麻烦的做法

了解这些麻烦后,我现在也养成了几个习惯:

  1. 发布前不 commit。文章在本地写完后先放着,等最终确认发布时再一次性提交。草稿阶段完全游离于 git 之外。

  2. 提交了没 push 前发现不对,立即 git commit --amend 修正,或者 git reset HEAD~1 回退。

  3. 敏感文件如果只有一次提交,用 git rebase -i 把对应 commit 删掉,比 filter-branch 轻太多。

  4. 把草稿放到 .gitignore 里。比如在 src/content/blog/ 下统一用 .draft.md 后缀,然后在 .gitignore 里加上 *.draft.md,让草稿永远不会被误提交。

  5. 使用本地分支。在本地 draft 分支上写文章,最终确认后再合并到主分支。即使不小心把 draft 分支 push 上去了,也不会污染主分支的历史。

当然,最根本的解法是:发布前多读两遍,别急着点提交。大部分的”想删除”其实都是”本不该发”。