Claude 代码每 10 分钟对项目仓库运行 `Git reset –hard origin/main`。
Claude Code runs Git reset –hard origin/main against project repo every 10 mins

原始链接: https://github.com/anthropics/claude-code/issues/40710

## Claude Code 每 10 分钟静默重置主分支 Claude Code (macOS 上的 2.1.87 版本) 存在一个严重错误:它每 10 分钟对用户项目仓库执行一次 `git fetch origin + git reset --hard origin/main`。 这会**静默地销毁所有未提交的跟踪文件更改**,而未跟踪的文件不受影响。Git 工作树不受影响。 通过 reflog 分析(显示一致的 10 分钟间隔)、实时复现和文件系统监控 (`fswatch`),进行了广泛的调查,证实了这种行为。 重要的是,git 操作**在 Claude Code 进程内部以编程方式执行**——没有启动外部 git 二进制文件。 排除了许多潜在原因,包括 git 钩子、插件、云同步服务和 IDE。 二进制分析表明,重置是通过处理获取和拉取的内部函数启动的。 影响很大:开发者可能会在没有警告的情况下丢失未提交的工作。 当所有更改都已提交时,问题会被掩盖。 解决方法包括使用 git 工作树或频繁提交。 由于编译后的二进制文件和有限的进程跟踪访问权限,根本原因——内部计时器和重置机制——仍然未知。

## Claude 代码与 Git 重置问题 - 摘要 有用户报告称 Claude 代码每 10 分钟在其项目仓库中重复运行 `git reset --hard origin/main`。 这引发了 Hacker News 上关于该事件、LLM 的本质以及适当保障措施的长时间讨论。 核心争论在于这是否是错误、用户配置问题,还是使用概率型 AI 工具进行代码操作的固有风险。 许多评论员强调,LLM 并非确定性的,即使有防护措施,也可能产生意外输出。 讨论的解决方案包括更严格的权限、沙盒、工具使用前钩子以阻止危险命令,以及转向更确定性的工作流程。 一个关键点是外部保障措施的重要性,因为仅仅依赖 LLM 对指令的“理解”是不可靠的。 一些用户报告了类似的问题,而另一些用户则没有遇到,这引发了关于可重复性和问题范围的疑问。 最终,该事件强调了在将 AI 编码助手集成到开发工作流程中时,需要谨慎和强大的安全措施。
相关文章

原文

Summary

Claude Code performs git fetch origin + git reset --hard origin/main on the user's project repo every 10 minutes via programmatic git operations (no external git binary spawned). This silently destroys all uncommitted changes to tracked files. Untracked files survive. Git worktrees are immune.

Environment

  • Claude Code version: 2.1.87 (Homebrew cask, compiled Bun binary)
  • OS: macOS 15.4 (Darwin 25.3.0, arm64)
  • Shell: zsh

Evidence

1. Git reflog: 95+ entries at exact 10-minute intervals

e8ea2c9 HEAD@{2026-03-29 22:19:09 +0200}: reset: moving to origin/main
e8ea2c9 HEAD@{2026-03-29 22:09:09 +0200}: reset: moving to origin/main
e8ea2c9 HEAD@{2026-03-29 21:59:09 +0200}: reset: moving to origin/main
e8ea2c9 HEAD@{2026-03-29 21:49:09 +0200}: reset: moving to origin/main
...
8792b6c HEAD@{2026-03-29 16:55:41 +0200}: reset: moving to origin/main
8792b6c HEAD@{2026-03-29 16:45:41 +0200}: reset: moving to origin/main
...
32aa7c7 HEAD@{2026-03-28 15:47:36 +0100}: reset: moving to origin/main
32aa7c7 HEAD@{2026-03-28 15:37:36 +0100}: reset: moving to origin/main

The second offset is consistent within each session but varies between sessions (:08, :36, :41, :09), confirming a timer tied to session start time with a 600-second interval. 95+ entries observed across 4 sessions over ~36 hours.

2. Live reproduction

  1. Modified src/lib/api.ts (tracked file) and created .canary-test.txt (untracked file)
  2. Monitored every 15 seconds
  3. At the next 10-minute mark, api.ts silently reverted — modification gone
  4. .canary-test.txt (untracked) survived
  5. Reproduced consistently across 4 consecutive cycles

3. fswatch caught the file operations

At the exact reset time, fswatch on .git/ captured:

23:59:10.349 .git/refs/remotes/origin/HEAD.lock  Created IsFile Removed AttributeModified
23:59:10.352 .git/logs/HEAD                       IsFile Updated
23:59:10.354 .git/refs/heads/main.lock            Created IsFile Removed AttributeModified

This is the classic pattern for git fetch origin + git reset --hard origin/main.

4. Only the Claude Code process is a candidate

lsof confirms the Claude Code CLI process (PID 70111, claude --dangerously-skip-permissions) is the only process with CWD in the affected repo. Two other Claude CLI sessions are in different directories.

5. No external git binary spawned

Process monitoring at 0.1-second intervals found zero git processes around reset times. The operations are programmatic (libgit2 or similar) within the Claude Code process, confirmed by .git/ lock file creation without any external process.

6. Worktrees are immune

The worktree reflog shows zero reset: moving to origin entries. The reset targets the main working tree only.

What was ruled out

A thorough investigation eliminated all external causes:

Cause Verdict Detail
Git hooks Cleared All .sample (inactive). No husky/lint-staged.
Claude Code user hooks Cleared Only peon-ping (audio). None reference git.
Plugin marketplace updater Disproven Deleted ~/.claude/plugins/marketplaces/ — resets continued unchanged.
macOS cloud sync Cleared No sync tool covers this directory (checked iCloud, Dropbox, Syncthing, Synology, Google Drive).
Cron/LaunchAgents Cleared No crontab. No LaunchAgent does git operations on this path.
Vite/SvelteKit dev server Cleared All file writes go to output dirs. Zero git awareness in source.
IDE/editors Cleared nvim in different repo. No format-on-save.
Time Machine Cleared Local snapshots are read-only APFS.
File watchers Cleared No fswatch/entr/watchman/guard running.

Binary analysis (partial)

From the compiled binary at /opt/homebrew/Caskroom/claude-code/2.1.87/claude:

  • hg1() function does ["fetch","origin"] via t_(C8(), _) without explicit CWD, defaulting to process.cwd()
  • io1() function is a git pull wrapper logging git pull: cwd=${H} ref=${_??"default"}
  • fileHistory state tracks {snapshots: [], trackedFiles: new Set, snapshotSequence: 0}
  • The exact timer/setInterval setup could not be identified in minified code

Impact

Any uncommitted changes to tracked files in the main working tree are silently destroyed every 10 minutes. During a 2-hour session, changes had to be re-applied 3+ times before the cause was identified. The bug is invisible when all changes are committed (the reset is a no-op), making it appear intermittent.

Question for the Claude Code team

What internal mechanism runs git fetch origin + git reset --hard against process.cwd() every 600 seconds? This could not be determined from the outside due to the compiled binary and lack of sudo for process tracing.

Workarounds

  1. Use git worktrees — confirmed immune (zero reset entries in worktree reflog)
  2. Commit frequently — committed changes survive the reset

Related issues

联系我们 contact @ memedata.com