侧边栏壁纸
博主头像
一笑痕

人生若只如初见,
是可喜亦或者是可悲?

  • 累计撰写 241 篇文章
  • 累计收到 7 条评论

工作树目录删了,Git 还保留哪笔登记?

2026-10-25 / 0 评论 / 5 阅读

工作树目录删了,Git 还保留哪笔登记?

把一个 linked worktree 目录直接删掉,磁盘上看似已经收干净,回到主仓库执行 git worktree list,那条工作树记录却还在。Git 记住的不只是目录本身:每个 linked worktree 还有一份放在主仓库管理区里的登记。目录消失后,登记不会自动跟着被文件管理器删除。

目录不在,登记仍在

linked worktree 的工作目录有自己的文件,但 .git 通常是一个指向主仓库内部管理记录的文件。主仓库会在 .git/worktrees/ 下保留对应的元数据。手动删目录时,这两处不是同一个对象:工作目录被移除,主仓库里的管理记录没有被触碰。

我在临时仓库里创建一个 detached worktree,再用 Python 删除它的目录。运行 git worktree list --porcelain,Git 仍列出主工作树和那条已失联的路径,并在末尾标出原因:

prunable gitdir file points to non-existent location

这是 Git 的发现,不是仓库损坏的判决。记录还在,Git 才能指出它原本指向哪里;prunable 表示它符合清理条件。脚本和完整输出分别保存在 tools/verify-tools-git-worktree-prune.py、tools/verify-tools-git-worktree-prune.log。实验只在系统临时目录里操作,退出后目录自动清除。

dry-run 只预览,不删记录

清理前可以先运行:

git worktree prune --dry-run --verbose --expire=now

本机用这组选项跑完后,Git 把 Removing worktrees/linked: gitdir file points to non-existent location 写到标准错误;再查 git worktree list --porcelain,那条记录仍标为 prunable。这行是预览,不代表登记已经删除。日志原文是:

stderr: Removing worktrees/linked: gitdir file points to non-existent location

所以不能把 Removing 这个词直接读成已经动手清理;dry-run 结束后还要看状态。至少在这次 Git 2.50.1(Apple Git-155)实验中,列表比单看提示词可靠。

prune 清的是哪一层

接着在同一临时仓库执行不带参数的 git worktree prune --verbose,重新列出工作树时,刚才那条记录已经不见,只剩主工作树。此处观察到的是本机版本的默认行为;如果仓库配置了过期策略,或运行在别的 Git 版本上,结果需要按实际环境确认。默认 prune 在标准错误中报告了移除动作;后续的 --expire=now 调用则没有标准输出或错误输出。判断清理是否生效,要比较调用前后的工作树列表,不能只看终端是否打印了提示。

为单独验证强制过期选项,脚本再创建一棵新工作树、删除其目录,然后执行 git worktree prune --expire=now。命令结束后再次列出登记,只剩主工作树,管理区里的失联记录也不存在。日志中的关键输出原样如下:

== list after prune ==
verified: stale worktree registration removed

--expire=now 把过期时间界限设为现在,适合清理已确认失效的登记;它不负责找回被删掉的工作区内容。这里的目录在执行 prune 前已经不存在,删掉的是仍留在仓库管理区里的记录。若目录里还有尚未提交的文件,直接从文件管理器删除并不能由 prune 补救。

先判断要清理的是什么

日常删除仍存在的工作树时,优先用 Git 自己的工作树管理命令,让它同时处理工作目录和登记;prune 面向的是目录已失联、登记成了孤儿的情况。二者的对象不同,不能把 prune 当成通用的「删除 worktree」快捷键。

排查时先看 git worktree list --porcelain。若记录仍对应一个需要保留的目录,就不要 prune;若路径已被有意删除,再看 prunable 提示,并用 dry-run 检查影响。此后是否运行普通 prune 或指定 --expire=now,取决于仓库的过期策略和清理时机。不建议只凭终端里没有报错就清理,先确认列表里的目标确实失联,能避免把管理记录与有效工作目录混为一谈。

    🤞 分享