目录

Hugo 部署最佳实践:正确配置 .gitignore 避免构建产物污染仓库

从 3688 个文件误提交事件学到的教训

事件回顾

Git 仓库污染对比:干净源码 vs 构建产物淹没

就在今天(2026-08-03),我经历了一次 Git 仓库污染事件。

事情是这样的:我想从 Hugo 博客仓库中移除 public/ 目录的 git 跟踪。这个目录包含 Hugo 构建生成的静态文件(HTML、CSS、JS、图片等),理论上应该被 .gitignore 排除,不应该进入版本控制。

但当我执行 git rm -r --cached public/ 时,遇到了 Git 锁文件问题。经过反复折腾,最终成功移除了 3688 个文件的跟踪记录,并推送到 GitHub。

问题症状

现象:执行 git rm 命令时,反复遇到以下错误:

fatal: 无法创建 '/data/oklifeme/.git/index.lock':文件已存在。

似乎另一个 Git 进程在这个仓库中运行,例如:'git commit' 命令打
开了一个编辑器。请确认所有进程都已经关闭然后重试。如果仍然报错,
可能之前有一个 Git 进程在这个仓库中异常退出:
手动删除这个文件再继续。

根本原因:之前的 Git 操作(可能是 GitHub CLI 或某个终端进程)异常退出,导致 .git/index.lock 锁文件残留。

Git 锁文件故障 - 终端报错与红色锁图标

排查过程

第一步:检查锁文件

ls -la /data/oklifeme/.git/index.lock

发现锁文件存在,大小只有 0 字节(说明进程已经退出,但文件未被清理)。

第二步:检查是否有 Git 进程

ps aux | grep -i "git" | grep -v grep

发现两个 GitHub CLI 进程:

oklife     85761  0.0  0.1 1493964 73392 ?       Ssl  09:43   0:00 node /home/oklife/.local/bin/github
oklife     54049  0.1  0.1 1493688 73788 ?       Ssl  09:37   0:00 node /home/oklife/.local/bin/github

这些进程可能是之前命令的残留。

第三步:强制删除锁文件

rm -f /data/oklifeme/.git/index.lock

第四步:重新执行 git rm

cd /data/oklifeme
git rm -r --cached public/

这次成功执行,输出了类似:

rm 'public/tags/鬼谷子/index.html'
rm 'public/tags/鬼谷子/index.xml'
rm 'public/zh-cn/index.html'
rm 'public/zh-cn/sitemap.xml'

第五步:验证结果

git ls-files public/ | wc -l
# 输出:0

确认 public/ 目录已不再被 git 跟踪。

五步排查流程图

正确配置 .gitignore

为了避免将来再次出现这个问题,应该确保 .gitignore 文件包含以下内容:

# Hugo自动生成的目录,禁止跟踪
public/          # Hugo 生成的静态网站文件(运行 hugo 后产生),无需版本控制
resources/       # Hugo 的资源缓存目录(如图片处理后的文件),无需跟踪
.hugo_build.lock # Hugo 构建时的锁文件,不应提交

# 其他常见忽略规则
node_modules/    # 如果使用 npm 依赖
*.log            # 日志文件
*.swp            # Vim 等编辑器的交换文件
.DS_Store        # macOS 的文件夹属性文件
Thumbs.db        # Windows 的缩略图缓存文件
.gitignore 正确配置示例 - VS Code 深色主题

常见问题 FAQ

Q: Hugo public/ 目录可以提交到 Git 吗?

不建议public/ 是 Hugo 的构建输出,应该通过 CI/CD 流程自动生成。提交构建产物会:

  • 增加仓库体积
  • 可能导致构建冲突
  • 浪费带宽和存储空间

Q: 如何移除已提交的 public/ 目录?

使用以下命令:

git rm -r --cached public/
git commit -m "chore: 移除 public 目录跟踪"
git push

Q: Git 锁文件 index.lock 残留怎么办?

# 删除锁文件
rm -f .git/index.lock

# 检查是否有残留的 Git 进程
ps aux | grep -i "git" | grep -v grep

# 必要时终止进程
kill <PID>

Q: git rm 会删除整个 GitHub 仓库吗?

不会! git rm 只会移除指定的文件或目录的跟踪,不会影响仓库本身。

验证方法:

# 检查仓库是否还在
git ls-remote origin --heads

# 验证 public/ 已从 GitHub 删除
curl -s "https://api.github.com/repos/OWNER/REPO/contents/public" | jq '.message'
# 输出:Not Found(确认删除成功)

常见误区澄清

误区:“删除了 GitHub 仓库”?

在执行 git rm -r --cached public/ 并推送后,有人可能会产生误解:“是不是把 GitHub 仓库删了?”

答案:没有! 只是删除了仓库中的 public/ 子目录,仓库本身完好无损。

具体发生了什么

操作效果
git rm -r --cached public/从 git 跟踪中移除 public/ 目录下的所有文件
git push推送到 GitHub,GitHub 上的 public/ 目录消失
本地 public/ 文件夹仍然存在,只是 git 不再跟踪
GitHub 仓库完好,只是不再包含 public/ 目录

验证方法

检查本地 git 跟踪状态:

git ls-files public/ | wc -l
# 输出:0(不再跟踪)

验证 GitHub 上的删除:

# 使用 GitHub API 验证
curl -s "https://api.github.com/repos/OkLifeMe/OkLife/contents/public"
# 返回:404 Not Found(确认删除成功)

确认仓库本身还在:

git ls-remote origin --heads
# 输出:refs/heads/main (仓库完好)

关键区别

git rm --cached public/  →  只移除 git 跟踪,保留本地文件
git rm public/          →  同时删除本地文件和 git 跟踪
rm -rf public/          →  只删除本地文件,git 跟踪会报错
git push                →  同步到远程仓库

重要提醒git rm 操作永远不会删除整个 Git 仓库,只会影响被指定的文件或目录。GitHub 仓库本身的安全性和完整性不受影响。

git rm 操作误区澄清 - 左右对比图

教训总结

1. 构建产物不应进入版本控制

public/ 目录是 Hugo 的构建输出,应该通过 CI/CD 流程(如 Cloudflare Pages、GitHub Pages)自动构建和部署。将这些文件提交到 Git 仓库:

  • 增加仓库体积
  • 可能导致构建冲突
  • 浪费带宽和存储空间

2. 注意 Git 锁文件

Git 使用锁文件(index.lock)来防止并发写操作。如果 Git 进程异常退出,锁文件可能残留,导致后续操作失败。

解决方法

# 删除锁文件
rm -f .git/index.lock

# 检查是否有残留的 Git 进程
ps aux | grep -i "git" | grep -v grep

# 必要时终止进程
kill <PID>

3. 使用 git rm --cached 而非删除文件

# 只移除跟踪,不删除文件
git rm --cached public/

# 如果加上 -r,则递归处理子目录
git rm -r --cached public/

注意:加上 --cached 参数后,文件仍保留在本地,只是不再被 git 跟踪。

最终结果

经过这次折腾,成功:

  1. 从 Git 仓库中移除了 3688 个 public/ 文件
  2. 推送到 GitHub(验证 API 返回 404,确认删除成功)
  3. 更新了 .gitignore 确保不再误提交

现在 Hugo 仓库只包含源码(content/、layouts/、static/),构建产物由 CI/CD 流程自动生成。

Hugo CI/CD 正确部署流程

相关资源


关联阅读

  • [[kb-writer 模式D blog-pipeline 升级踩坑记录]]
  • [[Git 锁文件故障排查实录]]

参考来源