feat(list): flag a branch checked out in more than one worktree - #3606
Merged
Conversation
`git worktree add --force` can put one branch in two worktrees, and #3480 made the resulting ambiguity visible only at resolution time: a command that looks the branch up warns once, then picks whichever worktree git lists first. `wt list` showed nothing, so the two identical `feature` rows read as a rendering glitch. Both rows now carry `⧉` in the Status column's worktree-state position, ranked above the informational `⚑` mismatch flag (a force-added duplicate usually sits off-template too) and below `⊟`/`⊞`. The Path column, which previously appeared only for a location mismatch, now also appears for a duplicate: with the branch name repeated, the path is the only thing telling the rows apart. JSON reports it in both schemas: schema 1 as a `worktree.state` value, schema 2 as its own `worktree.duplicate_branch` flag alongside `branch_mismatch`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A seventh glyph in the worktree-state position bought little: the Status column is a dense alphabet the reader has to learn, and a duplicated branch is rare. Both states say one thing — this worktree's place in the branch ⇔ worktree map is irregular — and the table already tells them apart, since a repeated Branch cell is the duplicate and an odd Path cell the mismatch. `⚑` now covers both, at its existing dim-yellow styling (a symbol's color is part of its identity, so sharing the glyph means sharing the color). The worktree-state alphabet is back to six. The data model keeps the distinction: JSON has no cardinality budget, and reporting a duplicate sitting at the template path as `branch_worktree_mismatch` would be false — its path does match. Schema 1's `worktree.state` still names the cause, schema 2 keeps its own `duplicate_branch` bool, and the priority between the two ⚑ states now decides only which cause JSON reports. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
max-sixty
marked this pull request as ready for review
July 26, 2026 12:23
worktrunk-bot
approved these changes
Jul 26, 2026
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Follow-up to #3480. That PR made a duplicated branch checkout (
git worktree add --force <path> <branch>) visible at resolution time:worktree_for_branchwarns once per branch, then resolves to whichever worktree git lists first.wt listsaid nothing about it. Two rows namedfeature, and no column that explains why.The nearest thing to a signal was accidental. A force-added duplicate usually lands off-template, since the original holds the template path, so it picks up
⚑for the location mismatch — while the worktree at the template path, the onewtactually resolves to, carried no flag at all. Exactly backwards from what's useful.The framing from the request: a worktree in the wrong location gets a status flag; a worktree sharing its branch should get one too.
Solution
⚑now covers both, on every worktree of the duplicated branch, resolved one included. Which worktreewtpicks is git's listing order, so singling out the shadowed rows would imply a legitimacy the ordering doesn't carry.This started as a seventh glyph (
⧉) and collapsed onto⚑in the second commit. The Status column is a dense alphabet the reader has to learn, and the two states say one thing: this worktree's place in the branch ⇔ worktree map is irregular. Off-template path and branch-claimed-twice are both instances. The table already distinguishes them without a glyph — a repeated Branch cell is the duplicate, an odd Path cell the mismatch — so the flag only has to say "not a rendering glitch, look at the Path column". Sharing the glyph means sharing its dim-yellow styling, since the codebase treats a symbol's color as part of its identity; #3480's warning remains the loud channel, firing the moment any command resolves the branch.The Path column comes along. It previously appeared only for a location mismatch, on the reasoning that the path is otherwise redundant with the branch. A duplicate inverts that: the branch name no longer identifies the row, and the path is the only thing telling the two apart. The layout flag is renamed from
has_branch_worktree_mismatchtopath_is_informativeto say what it now means.The data model keeps the distinction. JSON has no cardinality budget, and reporting a duplicate that sits at the template path as
branch_worktree_mismatchwould be false — its path does match. Schema 1'sworktree.statenames the cause ("duplicate_branch"), schema 2 gets its ownworktree.duplicate_branchbool besidebranch_mismatch, matching that schema's one-fact-per-field shape. The priority between the two⚑states now decides only which cause JSON reports.Detection is one pass over the worktree list (
duplicated_branches, next to #3480'sworktree_paths_for_branch), in memory, pre-skeleton, no git calls.Testing
test_worktree_paths_for_branch_detects_duplicatesgains the set form and a detached-HEAD worktree, which has no branch to duplicate.test_metadata_worktree_state_prioritycovers the two⚑states' ordering and both yielding to⊟/⊞.test_list_duplicate_branchsnapshots the table above, showing both flagged rows and the Path column earning its place.test_list_duplicate_branch_jsonasserts both schemas flag exactly the two duplicated rows.The flag only fires on a state no prior test sets up, so the only snapshot churn is the help pages and the schema-2 envelope's new field.