Skip to content

Latest commit

 

History

74 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

♻️ wtgc

CI MIT License

Find the worktrees eating your disk. Remove only the ones Git can prove you no longer need.

🌟 Highlights

  • Dry-run means dry-run. wtgc shows its working and changes nothing until you explicitly choose --yes or --interactive.
  • Conservative on purpose. Dirty, untracked, unmerged, locked, detached, primary, and ambiguous worktrees are kept.
  • Scan more than one repository. Start at a common root and discover repositories with nested worktrees.
  • The disk bill is itemised. See every worktree's status and size, plus the total space you could reclaim.
  • Works in scripts. JSON output supports hooks and scheduled jobs without changing the cleanup rules.

ℹ️ Overview

One-worktree-per-task workflows are excellent at creating isolated checkouts and terrible at reminding anyone to remove them. The audit that prompted wtgc found 350+ registered worktrees across five repositories and more than 30 GB tied up in directories whose branches had already landed.

Git already knows most of what is needed to clean this up; it just makes you assemble the evidence yourself. wtgc does that boring part. It checks the registered worktree, local default-branch ancestry, remote reachability, and working-tree state before calling anything removable.

🛡️ How eligibility is proved

clean + merged locally + reachable remotely + not protected = eligible

Squash merges can be proven with explicit --provider github confirmation, which binds the pull request to the exact branch SHA and mapped upstream.

For a live worktree, missing proof means it stays. False negatives waste disk; false positives destroy work. Given that choice, wtgc leaves the worktree alone. Live worktrees are removed through git worktree remove, never raw rm -rf, and local branch deletion is a separate opt-in action.

Stale records are handled separately. If Git marks a missing worktree path as prunable, wtgc may remove its registration with git worktree prune --expire=now; it does not delete a directory. The complete safety contract documents every refusal and revalidation rule. For unattended dry-run guidance, see the harness documentation.

🚀 Usage

Point wtgc at the directory containing your repositories:

wtgc clean --scan-root "$HOME/Projects"

Running wtgc without arguments prints this usage and exits. Use the explicit clean command when you want to start a scan; flags may also be supplied without the command token for compatibility. The bare invocation never recursively scans the directory where the shell happens to be running.

Every run is a dry-run unless you request a removal mode. It explains each decision without changing the filesystem. Abridged output:

PATH                                  BRANCH      CLASSIFICATION  DIRTY  ACTION        SIZE     RECLAIMED  REASON
/Users/me/Projects/app-worktrees/42   feature/42  safe_to_remove  clean  would_remove  1.8 GiB  0 B        clean branch tip is reachable from both the default branch and a remote-tracking ref

Summary:
  dry run: true
  repositories: 12
  scanned: 38
  safe: 4
  removed: 0
  potential reclaimable: 6.3 GiB
  reclaimed: 0 B

When the preview looks right:

# Remove every worktree proven safe
wtgc clean --scan-root "$HOME/Projects" --yes

# Or confirm each action yourself
wtgc clean --scan-root "$HOME/Projects" --interactive

# Emit machine-readable inventory instead
wtgc clean --scan-root "$HOME/Projects" --json

Worktree removal keeps the local branch. Add --delete-branch only when you also intend to delete branches after their worktrees are safely removed. Provider-confirmed squash candidates always retain their local branch, so an interactive prompt states that outcome before removing the worktree.

Git commands have no deadline by default. For hooks and scheduled jobs, set WTGC_GIT_TIMEOUT=2m (or another positive Go duration) to apply a deadline to each Git command.

⬇️ Installation

Homebrew (recommended)

Install the latest stable release from the wtgc formula:

brew tap ben-ranford/tap
brew install wtgc

Optional: install from source

For development or an unreleased build, install directly with Go:

go install github.com/ben-ranford/wtgc/cmd/wtgc@latest

Release automation is configured to publish prebuilt archives for Linux, macOS, and Windows on amd64 and arm64. Checksums and an SPDX SBOM will be published beside them on GitHub Releases. Stable releases also update the wtgc formula in ben-ranford/tap. GitHub records provenance as an artifact attestation. Verify a downloaded archive with:

gh attestation verify PATH/TO/WTGC_ARCHIVE -R ben-ranford/wtgc

See GitHub's attestation verification guide for details.

Runtime requirements:

  • Git 2.36+
  • An unambiguous remote default branch, such as origin/HEAD -> origin/main
  • Go 1.26.5+ only when installing from source

📖 The useful links

💭 Feedback and contributing

Questions and feature ideas belong in GitHub Discussions. Concrete bugs and feature requests belong in issues.

If wtgc calls a worktree safe and you think it is wrong, that is the important bug. Please report it with the Git state that produced the classification.

Contributions are welcome: start with CONTRIBUTING.md. Report suspected data-loss or command-execution vulnerabilities through the private process in SECURITY.md, not a public issue.

The support policy and Code of Conduct set expectations for help and participation.

wtgc was created by Ben Ranford and is available under the MIT License.

About

Worktree Garbage Collector - safely reclaim merged Git worktrees

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages