Observed Behavior
When worktrees associated with squash-merged GitHub pull requests are pruned, local branch deletion fails because git branch -d rejects branches whose commit history does not form a direct ancestry with the target branch. Despite this failure, _do_prune catches the exception, logs a warning, and returns True. The command summary then reports full success (1 pruned, 0 failed), misleading the user into believing the branch was removed when it was actually retained.
Expected Behavior
- Worktrees associated with merged pull requests (already cryptographically verified via GitHub PR
headRefOid == local_head) should have their local branches deleted cleanly (or handle squash-merge semantics safely).
- If branch deletion fails,
_do_prune must reflect the failure accurately, incrementing failed_count and reporting the failure in the final summary.
Steps to Reproduce
- In a repository, create and push a branch, open a PR, and squash-merge it on GitHub.
- In the local repository, run
treefort prune.
- Confirm prompt (
y).
- Git worktree directory is removed, but
git.delete_branch executes git branch -d -- <branch>, which exits with non-zero status:
error: The branch '<branch>' is not fully merged.
_do_prune catches CommandError, logs warning Failed to delete branch '<branch>': ..., but still returns True.
- Command reports:
Pruning complete: 1 pruned, 0 failed. Local branch still exists in git branch.
Minimal Reproduction Environment / Conditions
- Version / Branch / Commit:
release-v0.5.x@6d07c0c
- Component:
treefort.commands.prune.PruneCommand
- Trigger: Any GitHub PR merged via "Squash and merge" (default GitHub merge method)
Errors, Logs & Telemetry
WARNING: Failed to delete branch 'feature-squashed': Command failed, with exit status 1: git branch -d -- feature-squashed
INFO: Successfully pruned 'feature-squashed'
INFO: Pruning complete: 1 pruned, 0 failed.
Deliverables & Testing Requirements
- Address branch deletion for squash-merged PRs (once
local_head == pr.headRefOid confirms the branch was merged into the PR, determine whether force deletion -D or prompt is appropriate).
- Ensure
failed_count increments when branch deletion fails, and avoid logging Successfully pruned when a core step of pruning fails.
- Regression Safety: Add a unit test in
tests/commands/test_prune.py asserting that _do_prune returns False or reports failure when delete_branch raises CommandError.
Technical Pointers & Root Cause Clues
- Suspected Components:
src/treefort/commands/prune.py:44-52, 119-132 (_do_prune and __call__), src/treefort/git.py:87-90 (delete_branch)
- Related Commits:
bd7ed4c (Add new prune command for removing worktrees for merged PR branches)
Notes & Edge Cases
- Squash-merging is the predominant merge strategy on GitHub. Without addressing this, the majority of PRs pruned by users will leave stale branches behind.
Metadata
Severity / Priority: P0 (Blocker)
Area: bug, prune, git
AI Usage
Drafted with Gemini following the DEEP framework based on code review findings against release-v0.5.x. Reproduction conditions and code references were verified in the codebase.
Observed Behavior
When worktrees associated with squash-merged GitHub pull requests are pruned, local branch deletion fails because
git branch -drejects branches whose commit history does not form a direct ancestry with the target branch. Despite this failure,_do_prunecatches the exception, logs a warning, and returnsTrue. The command summary then reports full success (1 pruned, 0 failed), misleading the user into believing the branch was removed when it was actually retained.Expected Behavior
headRefOid == local_head) should have their local branches deleted cleanly (or handle squash-merge semantics safely)._do_prunemust reflect the failure accurately, incrementingfailed_countand reporting the failure in the final summary.Steps to Reproduce
treefort prune.y).git.delete_branchexecutesgit branch -d -- <branch>, which exits with non-zero status:error: The branch '<branch>' is not fully merged._do_prunecatchesCommandError, logs warningFailed to delete branch '<branch>': ..., but still returnsTrue.Pruning complete: 1 pruned, 0 failed.Local branch still exists ingit branch.Minimal Reproduction Environment / Conditions
release-v0.5.x@6d07c0ctreefort.commands.prune.PruneCommandErrors, Logs & Telemetry
Deliverables & Testing Requirements
local_head == pr.headRefOidconfirms the branch was merged into the PR, determine whether force deletion-Dor prompt is appropriate).failed_countincrements when branch deletion fails, and avoid loggingSuccessfully prunedwhen a core step of pruning fails.tests/commands/test_prune.pyasserting that_do_prunereturnsFalseor reports failure whendelete_branchraisesCommandError.Technical Pointers & Root Cause Clues
src/treefort/commands/prune.py:44-52, 119-132(_do_pruneand__call__),src/treefort/git.py:87-90(delete_branch)bd7ed4c(Add new prune command for removing worktrees for merged PR branches)Notes & Edge Cases
Metadata
Severity / Priority: P0 (Blocker)
Area:
bug,prune,gitAI Usage
Drafted with Gemini following the DEEP framework based on code review findings against
release-v0.5.x. Reproduction conditions and code references were verified in the codebase.