如何正确删除 Git Worktree

速览

git worktree remove <>          # 干净删除
git worktree remove --force <>  # 连同未提交改动一起删
git worktree prune                  # 清理残留引用

这三条命令覆盖 99% 的 worktree 删除场景。本文剩余部分解释什么时候用哪一条,什么会出错,以及如何恢复。


为什么不能直接 rm -rf

Worktree 头号错误是把它当普通文件夹对待:

rm -rf ../myapp-old-feature  # ❌ 别这么干

这只删掉了文件,但主仓库里残留了指向已消失 worktree 的元数据

.git/worktrees/myapp-old-feature/

现在 Git 以为 worktree 还在。你会遇到:

  • git worktree list 显示幽灵条目
  • git branch -d feat/old-feature 报错 "Cannot delete branch checked out at ..."
  • 某些 Git 操作抛奇怪警告

正确流程:用 git worktree remove —— 它同时处理文件和元数据。


干净路径:git worktree remove

git worktree remove ../myapp-old-feature

满足以下条件时成功:

  • ✅ Worktree 没有未提交改动
  • ✅ Worktree 没有未跟踪文件(或全部被 gitignore)
  • ✅ Worktree 没被锁定

Git 原子化地删除文件夹元数据。无残留状态。

删除后,分支本身还在:

git branch -d feat/old-feature   # 已合并分支
git branch -D feat/old-feature   # 强制(未合并)

如果 branch -d 时报 "Cannot delete branch" 错误,见 修复:无法删除被 worktree 使用的分支


干净删除被拒绝时:--force

worktree 有未提交改动时:

$ git worktree remove ../myapp-old-feature
fatal: '../myapp-old-feature' contains modified or untracked files, use --force to delete it

你的选项:

选项 A:先保存工作(推荐)

cd ../myapp-old-feature
git status                    # 有什么未提交的?
git stash                     # stash 起来
# 或
git add . && git commit -m "WIP"
# 或
git push origin HEAD          # 推到远程备份

cd -
git worktree remove ../myapp-old-feature

选项 B:强制删除(确定可丢弃时)

git worktree remove --force ../myapp-old-feature

--force 连带未提交工作一起删。无法恢复 —— 改动彻底没了。


清理残留 Worktree:prune

git worktree prune 扫描 .git/worktrees/,删除那些对应文件夹已不存在的元数据:

git worktree prune

以下情况用它:

  • 你(或队友)不小心 rm -rf 了 worktree 文件夹
  • 你把 worktree 放在了现在已断开的外部介质上
  • 崩溃留下孤儿元数据

-v 看清理详情:

git worktree prune -v
# Removing worktrees/myapp-crashed: gitdir file points to non-existent location

预览不实际清理:

git worktree prune --dry-run --verbose

锁定的 Worktree 先解锁

Worktree 可以被锁定以防误清理(比如放在不总连接的 USB 盘上):

$ git worktree remove ../myapp-on-usb
error: cannot remove a locked working tree, lock reason: USB drive

解锁再删:

git worktree unlock ../myapp-on-usb
git worktree remove ../myapp-on-usb

或强制穿过锁(文件夹真不可用时有风险):

git worktree remove --force ../myapp-on-usb

真实场景

场景 1:功能完成、干净合并

cd ~/projects/myapp-feat-auth
git push origin feat/auth
# 建 PR、合并
cd ~/projects/myapp
git fetch origin && git pull
git worktree remove ../myapp-feat-auth
git branch -d feat/auth

场景 2:放弃的实验

cd ~/projects/myapp
git worktree remove --force ../myapp-crazy-idea
git branch -D experiment/crazy-idea

场景 3:从 rm -rf 恢复

git worktree list            # 显示幽灵条目
git worktree prune -v        # 清理元数据
git branch -D feat/lost      # 现在能删分支了

场景 4:Worktree 在拔掉的外部盘上

git worktree list
# /Volumes/USB/myapp-backup  (unavailable: lock reason: USB offline)

git worktree unlock /Volumes/USB/myapp-backup
git worktree remove --force /Volumes/USB/myapp-backup
# 或者,如果你只想让 Git 忘了它:
git worktree prune

批量删除 Worktree

大扫除时,手上 10 个 worktree 等着干掉:

脚本:删除除主仓库外的所有 worktree

git worktree list --porcelain | awk '
  /^worktree / { wt=$2 }
  /^bare/ { next }
  /^$/ { if (wt && wt != main) print wt; wt="" }
  NR==1 { main=$2 }
  END { if (wt && wt != main) print wt }
' | xargs -I{} git worktree remove --force {}

⚠️ 这会丢弃除 main 外每个 worktree 的未提交改动。先干跑:

git worktree list --porcelain | awk '/^worktree / && $2 != "'"$(pwd)"'" { print $2 }'

交互式:用 fzf 选删

git worktree list | fzf -m | awk '{print $1}' | xargs -I{} git worktree remove {}

-m 允许 Tab 多选。比批量秒杀安全得多。


git worktree remove 不做的事

  • ❌ 不删除分支(那是 git branch -d
  • ❌ 不把分支推到 origin(先 commit/push!)
  • --force 之后不能恢复 —— 删了就删了
  • ❌ 不清理其他残留 worktree(那是 prune

清理脚本要把每一步写清楚。


为什么批量清理会变烦

如果你重度使用 worktree —— 比如每个 AI 编程任务一个 —— 很快就堆起来。一周后:

myapp                       # 主
myapp-feat-auth             # 3 天前合并
myapp-feat-search           # 放弃了
myapp-bug-203               # 2 天前合并
myapp-explore-postgres      # 以后可能用?
myapp-refactor-api          # 进行中
myapp-docs-update           # 昨天合并

终端清理仪式很快变无聊。这就是 ParallelCode 解决的问题:所有 worktree 在一个看板里,状态、最后活动、合并状态、一键"归档"或"删除"。

下载 ParallelCode → —— 免费,花 30 秒装上,永远不再手动 git worktree prune


总结:删除清单

git worktree remove 前:

  • 你提交或推送了工作吗?(git status 进 worktree)
  • 你也想删除分支吗?(删完 worktree 再 git branch -d
  • Worktree 锁定了吗?(git worktree unlock
  • 文件夹还在吗?(不在 → git worktree prune

命令:

git worktree remove <>          # 99% 的情况
git worktree remove --force <>  # 接受数据丢失
git worktree prune                  # 文件夹已消失
git worktree unlock <>          # 锁定时
git branch -d <>                # 删完 worktree 再删分支

延伸阅读