worktree remove: delete git worktrees
Remove one or more worktrees.
worktree remove [branch]worktree remove [branch] --forceworktree remove <branch> --force --jsonExamples
Section titled “Examples”worktree remove feature/add-bulk-actionsworktree remove feature/add-bulk-actions --forceworktree rm feature/add-bulk-actionsThe alias rm is available for remove.
The confirmation prompt
Section titled “The confirmation prompt”Naming a branch removes that worktree after one confirmation. The prompt says what you stand to lose, rather than asking a bare “are you sure”:
This branch is 1 commit ahead so you might lose some work. Are you sure you want to remove this worktree?This branch has 3 uncommitted changes so you might lose some work. Are you sure you want to remove this worktree?Commits count here even when the branch was never pushed. Where there is no upstream the
count is taken against origin/HEAD, falling back to
defaultSourceBranch. If neither resolves the count cannot be taken
at all, and the prompt says that instead of implying there is nothing to weigh:
Unpushed commits could not be counted for this branch (no comparison base; set defaultSourceBranch or run git remote set-head origin --auto), so it may carry work that exists nowhere else. Are you sure you want to remove this worktree?A worktree with nothing at stake gets the plain question — and a branch whose commits are all already applied in the comparison base is one of those, however many of them there are. It is counted as ahead, because a squash merge and a rebase both give the same work new commit identities, but there is nothing in it to lose. Warning about those commits would teach you that this prompt does not mean anything, which is how the one that does gets waved through.
When an agent is working in the worktree
Section titled “When an agent is working in the worktree”If an agent session is working in the worktree you name, the prompt opens with that fact and then says whatever it would have said anyway:
An agent session (feature-one-1f) is working in this worktree. Are you sure you want to remove this worktree?remove warns here and does not refuse: it names one worktree that you chose. A session that is
only idle does not count, so nothing is added for it, and the run prints exactly what it printed
before sessions were looked up.
Removing has no default, so a non-interactive run needs -f
(--force) and a branch name: without -f it exits 2 with worktree: no default for confirmation to remove <branch>; pass -f, and with no branch it names <branchName> -f rather than showing the picker.
--force skips the prompt entirely, but it does not stay silent about an agent. If a session
was working in the worktree, remove prints a warning on stderr after removing it, and every
--json run (which needs --force) carries the same text in the document’s warnings:
Removed feature/add-bulk-actions while an agent session (feature-one-1f) was working in it.Unlike cleanup, remove names one worktree that you chose, so
--force here answers only the confirmation you would otherwise have been given.
Running remove with no branch shows a picker instead, grouped into branches that are safe
to delete and branches that are still active. Each entry carries the same detail
list shows, so unpushed commits are visible before you select
anything, and a worktree an agent session is working in is listed under the active branches
with its Agent: detail beside it. A session that is only idle leaves the worktree where it
was. Selecting an active branch asks the usual “not safe to delete” question, and
--force skips it and warns as above.
Detached worktrees
Section titled “Detached worktrees”A worktree on a detached HEAD is listed as (detached HEAD), and every one carries that same label, so a
name cannot tell them apart. Name the worktree by its path instead:
worktree remove /abs/repo.worktrees/scratch --forceAn argument is read as a path only when it is written as one — absolute, ., .., or starting with ./ or
../ — and as a branch name otherwise; remove "(detached HEAD)" reaches only the first. A path that names no
worktree exits 2 with No worktree to remove at "<path>"., and so does the worktree you are standing in:
the current worktree is never removed, detached or not. A detached worktree
has no branch, so remove and cleanup remove its directory and git’s record of it
without running git branch -D.
Herdr spaces and Rex sessions
Section titled “Herdr spaces and Rex sessions”With opener set to herdr, removing a worktree also closes the Herdr space
that was built around it, so the space does not outlive the checkout. With rex, it kills the Rex session
instead, but only one whose every shell is in that worktree; see
Rex Sessions.
With opener set to auto, remove asks every installed tool, not only the one it would open in today: a
worktree Herdr opened still has its space closed when you run remove from a plain terminal, or from inside
Rex. Both lookups run at once, a tool that is not installed is not asked, and one tool failing to answer is a
warning that does not stop the other from closing what it holds.
Only a worktree that was actually removed has its space closed. A branch that was not found, a
confirmation you declined and a removal that failed all leave the space alone — their checkouts are
still on disk. A failed close is a warning and the command still exits 0: by then the worktree is
already gone, so there is nothing to retry.
With opener unset, editor or none, nothing here applies and no Herdr or Rex process is started. A fixed
herdr or rex asks that tool only. See
Herdr Spaces.
JSON output
Section titled “JSON output”--json prints exactly one JSON document on stdout, on one line, and implies a
non-interactive run: nothing is asked, so it needs a branch name
and -f.
worktree remove feature/add-bulk-actions --force --json{"removed":[{"branch":"feature/add-bulk-actions","path":"/abs/repo.worktrees/feature/add-bulk-actions"}],"herdrSpacesClosed":["w5"],"rexSessionsClosed":[],"warnings":[]}| Key | Value |
|---|---|
removed |
the worktrees that were removed, each with its branch and path |
herdrSpacesClosed |
the Herdr workspace ids that were closed; [] when opener is neither herdr nor auto, or nothing was open |
rexSessionsClosed |
the Rex session ids that were killed; [] when opener is neither rex nor auto, or nothing was open |
warnings |
what went wrong without stopping the run, such as a Herdr space or Rex session that would not close |
The spinner lines and warnings go to stderr. A failure prints {"error":{"code","message"}} on stdout instead
and exits non-zero; the codes are listed under branch. A named branch
that does not exist is not_found, a missing -f is missing_value, and a removal that did not happen is
failed — with --json, “nothing removed” is never reported as a success. When git refused the removal, its
reason is in the message (Could not remove the worktree <branch>: fatal: …); without --json the same line
goes to stderr and the exit is 1.