Claude
Skills
Sign in
Back

tidy-git

Included with Lifetime
$97 forever

Mechanical git repo hygiene. Prunes stale remote-tracking refs, deletes merged local branches (with confirmation), and reports stashes, untracked files, and unpushed work. Never touches remote state. Safe by default — destructive operations require explicit operator approval.

Data & Analytics

What this skill does


# Tidy-Git - Mechanical Repo Hygiene

Cleans up local git state that accumulates over time: remote-tracking refs for branches that no longer exist upstream, local branches that have already been merged, stale worktree references. Surfaces (without acting on) other state worth knowing about: stashes, untracked files, branches with no upstream, branches ahead of upstream, local-only tags.

**Scope of action:** local repo only. The skill never pushes, never force-pushes, never deletes anything on the remote. It also never deletes unmerged work, never deletes the current branch, never deletes the main branch.

**Reversibility note:** branches deleted by this skill can be recovered from `git reflog` for ~90 days. Tags and stashes are not deleted by this skill (the user makes those calls).

## Philosophy

**Tidy, not review.** The user invoked `/tidy-git` because they want cleanup, not analysis. The skill defaults to *doing* the safe operations rather than presenting findings for approval. Operator approval is required only for the borderline-safe operations (merged-branch deletion) where a preview is genuinely useful.

**Find→fix seam stays small.** This skill exists in the `/tidy-*` namespace because the seam between "detect a stale ref" and "delete it" is essentially zero. Adding a review-and-approve step for every mechanical operation would turn a 5-second cleanup into a 5-minute interactive session.

**Boundary respected: local only.** Repo hygiene that touches the remote (e.g., deleting remote branches, force-pushing to clean up history) is out of scope. Those operations have non-local effects and warrant explicit per-action operator decisions, not bundled into a "tidy" workflow.

## Workflow Overview

```
┌──────────────────────────────────────────────────────┐
│                    TIDY-GIT                          │
├──────────────────────────────────────────────────────┤
│  1. Detect repo context (main branch, current        │
│     branch, remote)                                  │
│  2. Run zero-risk auto-operations                    │
│     ├─ Prune remote-tracking refs                    │
│     └─ Prune stale worktree refs                     │
│  3. Inventory borderline-safe operations             │
│     └─ Merged local branches (excluding main +       │
│        current)                                      │
│  4. Inventory informational state                    │
│     ├─ Stashes (with age)                            │
│     ├─ Branches with no upstream                     │
│     ├─ Branches ahead of upstream                    │
│     ├─ Local-only tags                               │
│     └─ Untracked files                               │
│  5. Present preview + confirm for branch deletion    │
│  6. Execute approved deletions                       │
│  7. Final summary                                    │
└──────────────────────────────────────────────────────┘
```

## Workflow Details

### 1. Detect Repo Context

Run the following checks before any cleanup:

- **Is this a git repo?** `git rev-parse --is-inside-work-tree`. If not, abort cleanly.
- **What is the main branch?** Try in order: `git symbolic-ref refs/remotes/origin/HEAD` (the canonical answer if `origin/HEAD` is set), then check for `main`, then `master`. If none detected, ask the user.
- **What is the current branch?** `git branch --show-current`. Note for safety checks.
- **Is the working tree clean?** Not a blocker, but worth noting in the summary — it's informational state.

Record the main branch and current branch for safety checks in later steps. These two branches are never deleted by this skill.

### 2. Run Zero-Risk Auto-Operations

These operations remove only *references* — they never delete commits, objects, or files. Run without operator confirmation; they cannot lose work.

**2a. Prune remote-tracking refs.**

```
git remote prune origin
```

Removes local refs under `refs/remotes/origin/` for branches that no longer exist on the remote. Record the count removed.

If the project has multiple remotes, prune each one in turn.

**2b. Prune stale worktree refs.**

```
git worktree prune
```

Removes references to worktrees whose directories have already been deleted from disk. Does not touch worktrees that still exist. Record the count removed.

### 3. Inventory Borderline-Safe Operations

#### Merged local branches

Identify local branches that have been fully merged into the main branch:

```
git branch --merged <main-branch>
```

**Exclude from the list:**
- The main branch itself
- The current branch (`git branch --show-current`)
- Any branch passed as a `--keep` argument by the user (future extension)

For each remaining branch, also record:
- Last commit SHA (so the user can recover via reflog if they regret the delete)
- Last commit date and message (for the preview)
- Whether the branch has an upstream (informational)

**Caveat to surface in the preview:** `git branch --merged` only detects branches whose tip commit is reachable from the main branch. Branches that were merged via *squash-merge* or *rebase-merge* will NOT show up here — their tip commit is different from anything on main. Those branches will surface in step 4's "branches ahead of upstream" category, where the user can decide.

### 4. Inventory Informational State

These are reported but never modified by the skill.

**4a. Stashes.** `git stash list --date=relative`. Record count and the list. Stashes are never deleted by this skill — the user decides if they want to drop or apply.

**4b. Branches with no upstream.** `git for-each-ref --format='%(refname:short) %(upstream)' refs/heads/` and filter for empty upstream. These are local branches that have never been pushed (or whose upstream was deleted without removing the local branch). Surface as informational — they might be intentional local-only work or forgotten branches.

**4c. Branches ahead of upstream.** For each branch with an upstream, check `git rev-list --count <branch>@{u}..<branch>`. If non-zero, the branch has commits not on the remote. Report each with the count of commits ahead. Useful for spotting forgotten pushes.

**4d. Local-only tags.** Compare `git tag` against `git ls-remote --tags origin` (or the configured remote). Tags present locally but not remotely are local-only. These may be intentional backups (e.g., `pre-rebase-backup-*`) and are reported without action. Surface them so the operator can review and drop manually if desired.

**4e. Untracked files.** `git status --porcelain` and filter for untracked. Report count and a representative sample (cap at 10 names; collapse the rest). Not deleted by this skill — `/pre-compact` handles session-trash cleanup with judgment; this skill stays out of that lane.

### 5. Present Preview + Confirm

If step 3 found merged branches eligible for deletion, present them and ask for confirmation:

```
## Branch deletion preview

The following local branches are fully merged into <main> and are
safe to delete. Their SHAs are preserved in git reflog for ~90 days
if you need to recover.

  feat/old-feature        (last commit: 2026-04-15, sha 4a3b2c1)
  fix/typo-readme         (last commit: 2026-04-22, sha 9f8e7d6)
  feat/old-experiment     (last commit: 2026-03-08, sha 1a2b3c4)

Delete all? Select specific? Keep all?
```

Use `AskUserQuestion`. Default to "delete all" since the operator invoked the skill expecting cleanup.

**Three responses:**
- **Delete all** — proceed to step 6 with the full list.
- **Select specific** — operator picks a subset; proceed to step 6 with the selection.
- **Keep all** — skip step 6 and proceed to the summary.

**If step 3 found no merged branches:** skip directly to the summary. No preview needed.

### 6. Execute Approved Deletions

For each approved branch:

```
git branch -d <branch-name>
```

Use the **lowercase `-d`** (safe delete) — it refuses to delete a branch that isn't actually merged. This guards against rare cases where step 3's `--m

Related in Data & Analytics