Skip to content

fix: stop worktree list auto-refresh loop without linked worktrees#36

Merged
rrbe merged 1 commit into
mainfrom
fix/worktree-watch-loop
Jun 17, 2026
Merged

fix: stop worktree list auto-refresh loop without linked worktrees#36
rrbe merged 1 commit into
mainfrom
fix/worktree-watch-loop

Conversation

@rrbe

@rrbe rrbe commented Jun 17, 2026

Copy link
Copy Markdown
Owner

问题

grove 启动后,左侧 worktree 列表每 ~0.5 秒自动刷新一次,持续不停。仅在仓库没有 linked worktree(只有主 worktree)时出现。

根因(已实测复现)

watcher.rs 用 fs watcher 检测外部 worktree 增删。当 .git/worktrees/ 不存在时,代码回退去监视整个 .git/ 目录

grove 每次 open_repo/reload 都对各 worktree 跑 git status。对于有未提交改动的工作树(几乎所有真实项目),git status 每次都锁索引刷新 stat 缓存,反复创建/删除 .git/index.lock。它是 .git/ 的直接子项 → 触发 watcher → 发出 worktrees-changed → 前端 loadRepoInner → 又 open_repo → 又 git status自循环。500ms 节流没断开循环,只是把它变成"每 0.5 秒刷一次"。

有 linked worktree 时监视 .git/worktrees/,嵌套的 index.lock 被 NonRecursive 正确过滤,所以 bug 只在无 linked worktree 时出现。

修复

  • src-tauri/src/watcher.rs:回调里加路径过滤——只对落在 .git/worktrees/(自身或内部)的事件作出反应,忽略 index.lock.git/ 噪音。记录实际监视路径,使 watcher 在首个 worktree 创建后从 .git/ 升级为 .git/worktrees/;并用 canonical 路径匹配 macOS FSEvents 上报的 /private/var 真实路径。
  • src/App.tsx:给 worktrees-changed 监听的 useEffect 补上 [repo?.repoRoot] 依赖,避免每次渲染都退订/重订。

验证

用真实 notify 8.2 复刻 grove 过滤逻辑实测:

场景 修复前 修复后
无 worktree,脏树,6 次 reload 的 git status 11 次虚假事件 → 无限循环 0
外部创建首个 worktree 1(正确响应)
有 worktree,主+linked 各 status 刷索引 0 0
外部新增第 2 个 worktree 1 1(正确响应)

cargo check 通过,clippy 无 watcher 告警。

When a repo has no linked worktrees, .git/worktrees/ does not exist, so
the fs watcher fell back to watching the entire .git/ directory. Grove's
own `git status` calls (run on every open_repo/reload) recreate
.git/index.lock on each invocation for a dirty working tree, which the
watcher reported as a direct child of .git/ and emitted as
worktrees-changed -> the frontend reloaded -> ran git status again ->
infinite refresh loop (paced to once per 500ms by the throttle).

Add a path filter so the callback only reacts to events inside
.git/worktrees/ (a worktree actually added/removed), ignoring index.lock
and other .git churn. Track the watched path so the watcher upgrades from
.git/ to .git/worktrees/ once the directory appears, and canonicalize it
to match the real paths FSEvents reports on macOS.

Also give the worktrees-changed listener effect a [repo?.repoRoot]
dependency so it no longer re-subscribes on every render.
@rrbe rrbe merged commit b5694db into main Jun 17, 2026
3 checks passed
@rrbe rrbe deleted the fix/worktree-watch-loop branch June 17, 2026 06:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant