← 返回首页

AI 自动化博客 git pull --rebase 致 177 篇文章 404 重大生产事故复盘 2026:永久标准 #24 起源与三重防御机制

git rebase 404 事故博客灾备AI 自动化流水线永久标准 #24reflog 救援force push 事故流水线架构pipeline post-mortemGitHub Pages 404生产事故复盘

我是程序员,也是一个用 cron + AI Agent 自动写博客的人。2026 年 6 月 4 日中午 12 点 17 分,我的 GitHub Pages 站点(yaohehe.github.io)突然 404 了一大批发过的文章 —— 5 月 19 日到 6 月 4 日期间发布的 177 篇文章全部 404,首页、搜索流量、Clarity 热图瞬间归零。

我从 git reflog 反推 root cause:12PM cron 在 12:08 跑了 git pull --rebase origin main(rebase 用远端 5/31 旧版作基底),然后 18:19 流水线 force push 把远端从 5/19~6/4 完整版回滚到 5/19 缺失的旧版。更糟的是我上午 11:00 的 ceecb9bf force push 已把 706 文件全 commit 进 main,但 12PM 任务 12:08 跑 rebase 把 5/19~6/3 内容从 commit 中丢失。

我 2 分钟内用 reflog + 工作树恢复了所有内容(git reset --hard 1ef91bbf + force push),但这次事故让我立了**永久标准 #24** —— cron 流水线从此禁用所有 git pull/rebase/push。本文是这次**真实生产事故**的完整复盘,含根因解剖、救援命令、三重防御机制部署清单。

事故时间线(精确到分钟)

时间事件影响
5/19开始用 cron + AI Agent 自动发文章工作流进入稳态
5/19~6/3累计发布 177 篇文章(含 CN + EN)索引 220 / 200
6/4 11:00我手动 `ceecb9bf` force push 706 文件远端 main 同步完整
6/4 12:0812PM cron 跑 `git pull --rebase origin main`rebase 用远端 5/31 旧版作基底
6/4 12:17Clarity 流量监控告警,首页 404GitHub Pages 推送失败
6/4 18:1918PM cron 跑 force push 推送把远端从完整版回滚到 5/19 缺失版
6/4 18:19**177 篇文章全部 404**(外部用户受影响)重大生产事故
6/4 18:21我从 git reflog 找到 1ef91bbf 完整 commit数据未丢
6/4 18:23`git reset --hard 1ef91bbf` + force push**2 分钟内恢复**

关键观察:reflog 还活着,说明所有 706 文件在本地没丢,只是远端 main 分支指针被错误 rebase 推到了旧位置。

根因解剖(3 层叠加失误)

根因 1:12PM cron 任务无防护地跑了 `git pull --rebase`

原始 12PM cron prompt 里有一段「保持本地与远端同步」的逻辑,AI 实现时直接调用了 git pull --rebase origin main

# ❌ 危险代码(原始 12PM 实现)
cd /root/.openclaw/workspace/yaohehe.github.io
git fetch origin
git pull --rebase origin main    # ← 致命:用远端作基底重放本地 commit
python3 generate-html.py
git add .
git commit -m "auto: 12PM batch"
git push                            # ← 如果 push 被拒可能 force push

问题:rebase 后,本地 main 分支的 commit 链被重写。如果远端有新 commit(我没看到的 force push),rebase 会"丢失"本地独有的 commit —— 这次事故正是这个机制把 5/19~6/3 的 177 篇文章 commit 内容从远端 main tree 中抹掉。

根因 2:我上午 11:00 的 force push 已把 706 文件全 commit 进 main

我手动 force push 了一次大更新(706 文件),把 5/19~6/4 的全部内容推上去了。但 12PM cron 在 12:08 又跑了 rebase —— rebase 用远端 5/31 旧版作基底,相当于把我的完整 706 文件 commit chain 用旧 chain 重写

# 事故前的远端 main 链
A---B---C---D---ceecb9bf (force push, 706 文件)
                              \
                               E---F (12PM 新增)
# rebase 后
A---B---C---D (远端 5/31 旧版)
            \
             E'---F' (12PM 新增但用旧 D 作基底)
# E' / F' 与原 E/F 内容相同,但 D 之前的所有 commit 都没了

根因 3:18PM 流水线 force push 把回滚后的 main 推送出去

18PM cron 用了 git push --force-with-lease,这个命令在 rebase 后会把当前 main 指针(指向 D 旧版)推送到远端 —— 远端 main tree 的 706 文件状态被抹平到 5/19 缺失版本。

三层叠加:手动 force push → 12PM 误 rebase → 18PM 再 force push,把整个 5/19~6/4 区间的内容从远端抹掉。

救援命令(2 分钟恢复)

我从 git reflog 找到最后一次正确的 commit 哈希 1ef91bbf(即 ceecb9bf 的 force push 之后),用以下命令恢复:

# Step 1:查看 reflog 找到正确 commit
git reflog | grep -E "ceecb9bf|1ef91bbf"
# 输出(示例):
# 1ef91bbf HEAD@{0}: commit: 706 files
# a3c4d5e6 HEAD@{1}: rebase finished

# Step 2:硬重置到正确 commit
git reset --hard 1ef91bbf

# Step 3:force push 推送
git push --force-with-lease origin main

# Step 4:验证 GitHub Pages
curl -I https://yaohehe.github.io/2026-05-29-claude-code-...-en.html
# HTTP/2 200 ✅

**关键观察**:reflog 默认保留 90 天,所有 commit 都在本地,只要不 git gc --prune=now 就不会丢。

永久标准 #24 升级:三重防御机制

事故后我立了永久标准 #24,把 cron 流水线的 git 操作彻底禁止。3 层防护:

防御层 1:所有 cron prompt 头部加 ⚠️ git 操作禁令

# ✅ 新规(所有 6AM/12PM/18PM/22PM cron prompt 头部固化)
⚠️ 严禁使用以下 git 命令(流水线内,4AM 兜底可):

✅ 只允许:

为什么不删 git 操作:4AM 健康检查和人工 debug 时偶尔需要 git log / git diff,只禁止破坏性命令。

防御层 2:4AM 健康检查加"远端 vs 本地文件数对比"

我在 4am-health-check.py 加了一个新检查(main() 函数 Step 3):

def check_remote_vs_local():
    """比对 GitHub 远端 main 文件数 vs drafts/ 已发布文件数"""
    # 拉远端文件清单(轻量 API 调用)
    remote_files = fetch_github_tree("yaohehe", "yaohehe.github.io", "main")
    local_published = load_pushed_manifest()  # .pushed_manifest.json

    diff = len(remote_files) - len(local_published)
    if abs(diff) > 10:  # 阈值 10
        send_alert(f"⚠️ 远端 vs 本地文件数差 {diff},疑似事故!")
        pause_all_cron_pipelines()  # 暂停推送任务

阈值 10 的理由:单次 batch 通常推送 2~6 篇文章,10 是安全冗余。

防御层 3:`.pushed_manifest.json` 推送记录 + 4AM 验证

.pushed_manifest.json 记录每次成功推送的文件路径:

{
  "schema_version": 1,
  "pushed": [
    {
      "path": "2026-05-29-claude-code-...-en.html",
      "timestamp": "2026-05-29T10:30:00Z",
      "commit_sha": "abc1234",
      "size": 32783
    }
  ]
}

4AM 验证脚本会:

1. 读 .pushed_manifest.json

2. 调用 GitHub Tree API 拿远端实际文件

3. 对比路径是否都存在 + mtime 是否匹配

4. 不存在 → 报警并恢复(用 publish-via-api.py 重新推)

publish-via-api.py 推送盲区(新发现)

事故后我重新审计 publish-via-api.py(GitHub Contents API 单文件推送工具),发现**它不创建 git commit**。这意味着:

这是双轨制 git 引用过期问题的根因(corrections.md 6/04 11:07 已记录)。

**修复**:4am-health-check.pysync_git_refs() 步骤,每 4 小时跑一次 git fetch origin(30s 超时,失败非阻塞)来同步引用:

def sync_git_refs():
    """同步远端引用,避免 publish-via-api 推送盲区"""
    r = run_cmd("git fetch origin", timeout=30, fatal=False)
    if r and r.returncode == 0:
        log("✅ git refs synced")
    else:
        log("⚠️ git fetch 失败(非阻塞,可能网络问题)")

事故后学到的 5 个永久教训

1. **git pull --rebase 在自动化流水线中是定时炸弹**。永远不要在 cron 里跑 rebase,宁可手动同步。

2. force push 是双刃剑。手动 force push 抢救后,必须立即在 cron 流水线加防护;否则下次 12PM 任务的 rebase 会把你抢救的内容再次抹掉。

3. GitHub Contents API 是单文件推送的正确路径。它不创建 commit、不会触发 rebase 冲突、本地 git log 不显示 —— 完美避开流水线 git 操作的所有坑。

4. **reflog 是最后防线**。GitHub Pages 404 后,90 天内都能从本地 reflog 找 commit 恢复,超过 90 天需要靠 git fsck --dangling 找回悬空对象。

5. 三重防御缺一不可:单加 prompt 禁令挡不住 AI 偶发跑 git 命令;单加 4AM 检查挡不住 12PM→18PM 短窗口事故;单加 .pushed_manifest 验证挡不住 manifest 自身损坏。

部署清单:5 步永久固化

把这次事故的修复固化为永久标准(每个新 workspace 必跑):

# Step 1:在所有 6AM/12PM/18PM/22PM cron prompt 头部加 git 操作禁令段
cat > /tmp/git-ban-snippet.txt << 'EOF'
⚠️ 严禁使用以下 git 命令(流水线内,4AM 兜底可):

✅ 只允许:
EOF

# Step 2:4am-health-check.py 加远端 vs 本地文件数对比
# (脚本已包含 main() Step 3 check_remote_vs_local())

# Step 3:创建 .pushed_manifest.json 模板
cat > .pushed_manifest.json << 'EOF'
{"schema_version": 1, "pushed": []}
EOF

# Step 4:4AM health check 加 .pushed_manifest.json 验证步骤

# Step 5:4am-health-check.py 加 sync_git_refs() 步骤(30s 超时,非阻塞)

适用场景

总结与下一步

这次事故让我把「AI 自动化流水线的所有 git 操作交给 publish-via-api.py 一个工具」立为永久标准。本地 main 指针永远不需要同步,因为 GitHub Contents API 推送只动文件不动 commit

下一步我会写一篇《publish-via-api.py 推送盲区实战复盘 2026》(已发于 2026-07-30),讲 5 个静默失败点 + 5 步根治修复,与本文形成「事故根因 + 推送工具深化」完整链路。

事实核对:所有时间戳、commit 哈希、命令、文件名均来自 corrections.md 6/04 20:30 条目;reflog 救援命令、4am-health-check.py 同步步骤、.pushed_manifest.json 格式均来自永久标准 #24 文档。)

👉 Join MiniMax Token Plan: AI coding acceleration for businesses

👉 立即参与小米 MiMo 开放平台:API 体验金 + 首单 9 折优惠

👉 Join Aliyun AI: Top AI products with exclusive coupons for business innovation

📌 This article was AI-assisted generated and human-reviewed | TechPassive — An AI-driven content testing site focused on real tool reviews

🔗 Recommended Tools

These are carefully selected tools. Using our affiliate links supports us to keep producing quality content:

☁️ DigitalOcean Cloud ⚡ Vultr VPS ⭐ MiniMax Token Plan 🧩 Zhipu Coding Plan 🎁 Zhipu 20M Tokens Gift 🤖 QoderWork CN (Refer & Earn) ☁️ Aliyun AI Products 📚 WordPress Books 🔍 WordPress SEO Books 🌐 Web Hosting Books 🐳 Docker Books 🐧 Linux Books 🐍 Python Books 💰 Affiliate Marketing 💵 Passive Income Books 🖥️ Server Books ☁️ Cloud Computing Books 🚀 DevOps Books
← 返回首页