Skip to content

Force orphan worktree cleanup to remove dirty worktrees#73

Merged
juliusmarminge merged 1 commit intomainfrom
codething/4ed1311b
Feb 19, 2026
Merged

Force orphan worktree cleanup to remove dirty worktrees#73
juliusmarminge merged 1 commit intomainfrom
codething/4ed1311b

Conversation

@juliusmarminge
Copy link
Copy Markdown
Member

@juliusmarminge juliusmarminge commented Feb 19, 2026

Summary

  • Add optional force support to git worktree removal in shared contracts and server git execution.
  • Update orphaned worktree cleanup in the sidebar flow to call remove with force: true.
  • Extend server git integration tests to cover dirty worktree behavior:
  • verify non-forced removal fails when the worktree has uncommitted changes.
  • verify forced removal succeeds and deletes the worktree directory.
  • Thread the optional force flag through the web React Query mutation to the API call.

Testing

  • Added integration test: removeGitWorktree force removes a dirty worktree in apps/server/src/git.test.ts.
  • Check included in test:
  • dirty worktree removal without force throws.
  • dirty worktree removal with force succeeds and directory no longer exists.
  • Lint: Not run.
  • Full test suite: Not run.

Open with Devin

Note

Medium Risk
Uses git worktree remove --force, which can discard uncommitted changes in the worktree; impact is limited to explicit cleanup paths and is covered by an integration test.

Overview
Enables optional forced git worktree cleanup by threading a force flag through the shared contract, web mutation, and server execution so callers can pass --force to git worktree remove.

Updates the thread deletion/orphaned worktree cleanup flow in Sidebar to always attempt removal with force: true, and adds a server integration test covering the dirty-worktree behavior (non-forced removal fails; forced removal succeeds and deletes the directory).

Written by Cursor Bugbot for commit 2d3263d. This will update automatically on new commits. Configure here.

Summary by CodeRabbit

  • New Features

    • Implemented forced worktree removal capability, allowing cleanup of worktrees with uncommitted changes when deleting threads.
  • Tests

    • Added comprehensive test coverage for forced worktree removal scenarios.

- add optional `force` to remove-worktree contract and server git args
- pass `force: true` from sidebar orphaned worktree cleanup flow
- add integration test covering dirty worktree removal behavior
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 19, 2026

No actionable comments were generated in the recent review. 🎉


Walkthrough

Adds an optional force flag to the git worktree removal functionality, allowing forced deletion of dirty worktrees. The flag is introduced in the schema contract, implemented in the backend git command, and propagated through the frontend mutation with a new test case validating the forced removal behavior.

Changes

Cohort / File(s) Summary
Schema & Contract
packages/contracts/src/git.ts
Added optional force: z.boolean().optional() field to gitRemoveWorktreeInputSchema for contract validation.
Backend Implementation
apps/server/src/git.ts
Modified removeWorktree to conditionally append --force flag to git command when input.force is true, building argument list incrementally.
Backend Test
apps/server/src/git.test.ts
Added test case validating forced removal of dirty worktrees, confirming rejection without force flag and successful deletion with force: true.
Frontend Query & Mutation
apps/web/src/lib/gitReactQuery.ts, apps/web/src/components/Sidebar.tsx
Updated gitRemoveWorktreeMutationOptions mutationFn signature to accept optional force parameter and pass it to API; updated Sidebar to invoke mutation with force: true when removing orphaned worktrees.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding force-based cleanup for orphan worktrees to handle dirty worktrees.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codething/4ed1311b

Comment @coderabbitai help to get the list of available commands and usage tips.

@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp bot commented Feb 19, 2026

Force removal of orphaned git worktrees by passing --force from web to server via GitCoreService.removeWorktree and related API

Add optional force to the remove worktree API and thread-deletion flow; update GitCoreService.removeWorktree to append --force when requested; extend the React Query mutation to accept force; add a test asserting forced removal of dirty worktrees.

📍Where to Start

Start with GitCoreService.removeWorktree in apps/server/src/git.ts, then review the API schema change in packages/contracts/src/git.ts and the web usage in apps/web/src/lib/gitReactQuery.ts.


Macroscope summarized 2d3263d.

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Feb 19, 2026

Greptile Summary

This PR adds force removal support for git worktrees to handle the cleanup of dirty worktrees during orphaned worktree deletion.

  • Added optional force boolean parameter to the GitRemoveWorktreeInput contract schema
  • Updated server's removeWorktree method to pass --force flag when requested
  • Threaded the force parameter through the web React Query mutation layer
  • Modified Sidebar's orphaned worktree cleanup to use force: true when removing worktrees after thread deletion
  • Added integration test verifying that forced removal succeeds on dirty worktrees while non-forced removal correctly fails

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • Clean implementation that threads a single optional parameter through the stack, well-tested with integration tests covering both success and failure cases, follows existing patterns, and solves a real problem (orphaned dirty worktrees)
  • No files require special attention

Important Files Changed

Filename Overview
packages/contracts/src/git.ts Added optional force boolean field to gitRemoveWorktreeInputSchema for forcing worktree removal
apps/server/src/git.ts Updated removeWorktree to pass --force flag to git when input.force is true
apps/web/src/lib/gitReactQuery.ts Extended mutation function signature to accept optional force parameter and pass it through to API
apps/web/src/components/Sidebar.tsx Updated orphaned worktree cleanup to call removeWorktreeMutation with force: true
apps/server/src/git.test.ts Added integration test verifying force removal succeeds on dirty worktrees while non-forced fails

Sequence Diagram

sequenceDiagram
    participant User
    participant Sidebar
    participant ReactQuery
    participant API
    participant GitService
    participant Git

    User->>Sidebar: Delete thread with orphaned worktree
    Sidebar->>ReactQuery: removeWorktreeMutation.mutateAsync({cwd, path, force: true})
    ReactQuery->>API: git.removeWorktree({cwd, path, force: true})
    API->>GitService: removeWorktree(input)
    GitService->>Git: git worktree remove --force {path}
    Git-->>GitService: Success (removes dirty worktree)
    GitService-->>API: void
    API-->>ReactQuery: void
    ReactQuery->>ReactQuery: Invalidate git queries
    ReactQuery-->>Sidebar: Success
    Sidebar-->>User: Worktree removed
Loading

Last reviewed commit: 2d3263d

@juliusmarminge juliusmarminge merged commit 58a8d65 into main Feb 19, 2026
5 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.

1 participant