Skip to content

Worktree cleanup misses local commits when branch has no upstream #476

Description

@cf-x

Problem

The worktree cleanup safety check can miss local-only commits and delete the only branch reference that reaches them.

create_worktree() creates wt/<name> with:

git worktree add <path> -b wt/<name> HEAD

The new branch has no upstream by default. However, _count_worktree_changes() counts commits with:

git log @{push}..HEAD --oneline

For a newly-created worktree branch this command exits with status 128 and writes no stdout:

fatal: no upstream configured for branch 'wt/demo'

The helper does not check either Git command's return code, so the empty stdout is interpreted as zero commits. A clean worktree containing a local commit can therefore pass the safety check. remove_worktree() then runs git worktree remove --force followed by git branch -D wt/<name>.

This affects:

  • s18_worktree_isolation/code.py
  • s19_mcp_plugin/code.py
  • s20_comprehensive/code.py

Reproduction

push_log_rc=128
computed_commits=0
actual_local_only_commits=1
worktree_clean=yes
error=fatal: no upstream configured for branch 'wt/demo'

Expected behavior

Cleanup without discard_changes=true should refuse when:

  • the worktree has uncommitted files;
  • the worktree branch contains commits not reachable from the main worktree's current HEAD; or
  • any Git status/history check fails.

Using the main worktree's HEAD as the reachability baseline avoids relying on an upstream that temporary worktree branches do not have. Error paths should fail closed.

Suggested coverage

  1. Clean worktree with no unique commits can be removed.
  2. Worktree with uncommitted files is preserved.
  3. Clean worktree with no upstream and a unique commit is preserved.
  4. Git status/history verification failures preserve the worktree.

This is not additional production hardening: it restores the safety behavior described in the s18 cleanup section, which says removal refuses by default when changes exist.

AI assistance was used to reproduce and analyze this issue; I reviewed and verified the report.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions