Skip to content

fix(subagent): track branch ownership during worktree cleanup - #4520

Merged
ErikBjare merged 2 commits into
gptme:masterfrom
wozhenbang2004:fix/worktree-branch-ownership
Oct 29, 2026
Merged

ErikBjare merged 2 commits into
gptme:masterfrom
wozhenbang2004:fix/worktree-branch-ownership

Conversation

@wozhenbang2004

@wozhenbang2004 wozhenbang2004 commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Closes #4519. Cleaning a worktree created on feature/task uses the directory basename task as the branch to force-delete. This leaves the worktree's branch behind and can delete an unrelated task branch. Smart cleanup also returns the truncated branch name.

Change

Record the exact branch created by gptme in the linked worktree's Git admin directory, then read that record before removing the worktree. The current HEAD is deliberately not used as ownership evidence: a worker can switch to an existing user branch. Legacy/external worktrees with no ownership record retain their branch refs instead of guessing. Working-tree removal behavior otherwise stays the same.

Four real-Git regression cases cover slash-separated names and unrelated refs, the smart-cleanup return value, switching to an existing branch, and worktrees without ownership metadata.

Validation

  • uv run pytest tests/test_git_worktree.py -q --no-cov --retries 0: 17 passed, independently rerun during review. The two slash-name cases fail on the original source.
  • Repository-pinned pre-commit Ruff check passes across all tracked files; the pinned formatting hook and git diff --check pass for the change.
  • Broad make test PYTEST_WORKERS=2 NO_COVERAGE=1: 14,954 passed, 41 failed, 285 skipped. This run began before the final ownership-record revision; the final worktree suite was rerun afterward. A follow-up rerun of those 41 cases on unchanged master reproduced 40 failures; one process-memory test passed on that rerun. The baseline run took 24.43 seconds. A full clean test run is not claimed.
  • make lint using lockfile Ruff 0.17.0 reports the same two existing ISC004 diagnostics in tests/test_tools_watch.py on both base and patch. The separately pinned pre-commit Ruff hook passes.
  • make typecheck reports 37 identical errors on base and patch, involving unavailable optional dependencies and their follow-on types. No full type-check pass is claimed.
  • No model API calls were needed.

AI assistance: OpenAI Codex assisted with investigation, implementation, regression tests, and an independent review.

@greptile-apps

greptile-apps Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; no actionable issues were found.

Summary

Records the full branch name in each worktree’s Git admin directory and reads it before cleanup.

  • Worktree cleanup follows the branch recorded when gptme creates the worktree.

wozhenbang2004 explicitly identifies retaining legacy and external branch refs as intentional.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Create worktree and new branch] --> B[Record full branch name]
    B --> C[Read ownership before cleanup]
    C --> D[Remove working directory]
    D --> E{Recorded branch?}
    E -->|No| F[Leave branch refs alone]
    E -->|Yes| G{Smart cleanup found changes?}
    G -->|Yes| H[Keep and return recorded branch]
    G -->|No| I[Delete recorded branch]
Loading

Reviews (1) · Last reviewed commit: "test(subagent): cover worktree branch ow..." · Reviewed by Greptile

@TimeToBuildBob TimeToBuildBob left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the clean reproduction and the ownership-record approach. GitHub was holding the first-contributor fork workflows; I approved those runs, so CI is in progress now.

The design looks right:

  • Recording the exact created branch in the worktree git admin dir is the correct ownership signal. Directory basename is wrong for slash-separated names; current HEAD is wrong after a worker checks out an existing branch.
  • Leaving refs alone when the marker is missing is the right default for legacy/external worktrees.
  • git branch -D -- is the right deletion form.
  • The four regression tests hit the actual failure modes (slash names vs unrelated refs, smart-cleanup return value, switched HEAD, missing marker).

No requested changes from the diff. If CI fails, that's yours to fix — this branch stays yours. I can look at a follow-up if something comes back red.

@codecov

codecov Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@ErikBjare
ErikBjare merged commit 5d437e2 into gptme:master Oct 29, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Worktree cleanup can delete an unrelated branch with a slash-separated name

3 participants