clean-git-repo
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseClean Git Repo
清理 Git 仓库
Report and clean up local branches, linked worktrees, stale remote-tracking
refs, worktree metadata, and tags. Run from either:
- a worktree or Git directory to handle one repository; or
- a worktree container whose immediate child directories are worktrees.
In container mode, the script groups children by their resolved Git common
directory and handles each repository once. It does not recurse beyond immediate
children. A bundled script does the deterministic detection and deletion; you
orchestrate the safety gates.
Resolve [scripts/clean-git-repo.sh][1] to an absolute path once and run it from
the target repository or worktree container, not the skill directory. In Claude
Code: .
SCRIPT="${CLAUDE_SKILL_DIR}/scripts/clean-git-repo.sh"bash
"$SCRIPT" # report only (dry run)
"$SCRIPT" --apply # delete the SAFE tierThe script's lists every flag; the key ones appear below.
--help报告并清理本地分支、关联 worktree、陈旧的远程跟踪 refs、worktree 元数据和 tags。可从以下任一位置运行:
- 一个 worktree 或 Git 目录,用于处理单个仓库;或
- 一个 worktree 容器,其直接子目录均为 worktree。
在容器模式下,脚本按解析得到的 Git common directory 对子项分组,并对每个仓库仅处理一次。它不会递归到直接子目录之外。内置脚本负责确定性的检测与删除;你负责编排安全门控。
将 [scripts/clean-git-repo.sh][1] 解析为绝对路径一次,并从目标仓库或 worktree 容器运行它,而不是从 skill 目录运行。在 Claude Code 中:。
SCRIPT="${CLAUDE_SKILL_DIR}/scripts/clean-git-repo.sh"bash
"$SCRIPT" # report only (dry run)
"$SCRIPT" --apply # delete the SAFE tier脚本的 会列出所有 flag;下面列出关键项。
--helpSafety model: confirm unless the action is safe
安全模型:除非操作安全,否则需要确认
| Tier | Actions | Confirmation |
|---|---|---|
| Safe | | none (apply + report) |
| Confirm | delete MERGED-but-advanced ( | ask the user first |
| Never | the current branch, default branch, | excluded by the script |
A linked worktree follows its branch's tier when it has no tracked or untracked changes, submodules, or non-disposable ignored files. Ignored content in and directories at any depth is disposable; other ignored files remain protected.
node_modules/dist/On apply, the script rechecks those conditions, runs without , and deletes the branch only if removal succeeds. Disposable ignored files are removed with the worktree. The script never force-removes a worktree.
git worktree remove--forceA branch is merged when GitHub () reports its PR merged, or its tip is
an ancestor of the base, so squash- and rebase-merges are caught, not just
fast-forwards. A squash-merged branch auto-deletes only when its tip is
contained in the merged PR head; if the local tip advanced past it (extra
commits that never reached the PR, or a merged head not fetched locally), it
drops to the confirm tier instead of being force-deleted.
gh--force-merged| 层级 | 操作 | 确认 |
|---|---|---|
| 安全(Safe) | | 无(apply + 报告) |
| 需确认(Confirm) | 删除 已合并但已前进( | 先询问用户 |
| 绝不(Never) | current 分支、default 分支、 | 由脚本排除 |
关联 worktree 在没有 tracked/untracked 变更、submodule 或不可丢弃的 ignored 文件时,遵循其分支的层级。任意深度下 和 目录中的 ignored 内容都可丢弃;其他 ignored 文件仍受保护。
node_modules/dist/执行 apply 时,脚本会重新检查这些条件,运行不带 的 ,并且仅在移除成功后才删除分支。可丢弃的 ignored 文件会随 worktree 一同移除。脚本绝不会强制移除 worktree。
--forcegit worktree remove当 GitHub()报告其 PR 已合并,或其 tip 是 base 的 ancestor 时,分支即视为 已合并,因此不仅 fast-forward,squash merge 和 rebase merge 也能被识别。只有当 squash-merged 分支的 tip 包含在已合并 PR 的 head 中时,才会自动删除;如果本地 tip 在此之后又前进了(存在从未进入 PR 的额外提交,或已合并的 head 尚未在本地 fetch),它会降级到 需确认层级,而不是被强制删除。
gh--force-mergedWorkflow
工作流
Copy this checklist and work through it:
- 1. Confirm the target: for one repository, or inspect the immediate child worktrees when the current directory is a container.
git rev-parse --show-toplevel - 2. Run the script with no flags to fetch+prune refs and print the categorized plan.
- 3. Relay the plan per repository: counts per tier, the SAFE list verbatim, and every worktree path that would be removed.
- 4. Apply the SAFE tier (). No confirmation needed; report what was deleted.
--apply - 5. For each non-empty CONFIRM tier, ask the user which to include, then
re-run with the matching opt-in flags (e.g.
--apply). To act on only a subset of a tier, delete those branches by name rather than passing the whole-tier flag. For an attached worktree, first run--apply --force-gone --stalewithoutgit worktree remove <path>; delete the branch only if removal succeeds.--force - 6. Verify: re-run with no flags and confirm the targeted tiers are now empty.
复制此 checklist 并逐项执行:
- 1. 确认目标:对于单个仓库,执行 ;如果当前目录是容器,则检查其直接子级 worktree。
git rev-parse --show-toplevel - 2. 不带任何 flag 运行脚本,以 fetch+prune refs 并打印分类后的计划。
- 3. 按仓库转述计划:每个层级的数量、SAFE 列表原文,以及每个将被移除的 worktree 路径。
- 4. 应用 SAFE 层级()。无需确认;报告删除了哪些内容。
--apply - 5. 对每个非空 CONFIRM 层级,先询问用户要纳入哪些项,然后使用相应的 opt-in flag 重新运行 (例如
--apply)。若只处理某一层级中的 子集,请按名称删除这些分支,而不要传入整个层级的 flag。对于已附加的 worktree,先运行不带--apply --force-gone --stale的--force;仅在移除成功后删除分支。git worktree remove <path> - 6. 验证:再次不带 flag 运行,确认目标层级现已为空。
Step 2: report
第 2 步:报告
bash
"$SCRIPT" # default 90-day stale threshold
"$SCRIPT" --age-days 180 # adjust the threshold the user confirmsRead the output. It groups branches as SAFE TO DELETE — merged, CONFIRM —
merged, local tip advanced, CONFIRM — gone upstream, CONFIRM — stale >
Nd, CONFIRM — matching remote branches, REMOTE SKIP, CONFIRM — local
tags absent from <remote>, PROTECTED, and a kept ACTIVE count.
upstream alone is not proof of a merge: it can also be a
closed-unmerged PR. GONE is therefore always a confirm tier; each gone entry
shows how many commits it holds ahead of the base, so you can see what a delete
would discard. Each stale entry carries its push-state (, , or ), so you can see
at a glance whether deleting it discards work that exists nowhere else. With
, review both remote sections: remote branches delete only when the
remote-tracking tip is identical to the local branch being deleted or
independently proven merged; otherwise they are reported as skipped. A branch
entry with also removes that safely removable linked
worktree when its tier is applied. Container mode prints a header for each
distinct Git common directory.
[gone]never pushed — local onlyahead N — unpushed workin sync with <upstream>--remote; worktree <path>bash
"$SCRIPT" # default 90-day stale threshold
"$SCRIPT" --age-days 180 # adjust the threshold the user confirms读取输出。它会将分支分为 SAFE TO DELETE — merged(可安全删除——已合并)、CONFIRM — merged, local tip advanced(需确认——已合并,但本地 tip 已前进)、CONFIRM — gone upstream(需确认——上游已删除)、CONFIRM — stale > Nd(需确认——超过 Nd 未处理)、CONFIRM — matching remote branches(需确认——匹配的远程分支)、REMOTE SKIP(远程跳过)、CONFIRM — local tags absent from <remote>(需确认——远程中不存在的本地 tags)、PROTECTED(受保护),以及保留的 ACTIVE(活动) 计数。
仅凭上游出现 并不能证明分支已合并:它也可能是已关闭但未合并的 PR。因此 GONE 始终属于需确认层级;每个 gone 条目都会显示它比 base 领先多少个提交,以便了解删除会丢弃什么。每个 stale 条目都带有其推送状态(〔从未推送——仅本地〕、〔领先 N 个提交——未推送的工作〕或 〔与 <upstream> 同步〕),因此可以一眼看出删除是否会丢弃仅存在于本地、其他地方不存在的工作。使用 时,请同时检查两个远程部分:只有当远程跟踪 tip 与待删除的本地分支相同,或已独立证明合并时,才会删除远程分支;否则会报告为跳过。带有 的分支条目,在应用其层级时还会移除可安全移除的关联 worktree。容器模式会为每个不同的 Git common directory 打印一个标题。
[gone]never pushed — local onlyahead N — unpushed workin sync with <upstream>--remote; worktree <path>Step 4 & 5: apply
第 4、5 步:应用
bash
"$SCRIPT" --apply # SAFE only (merged branches)
"$SCRIPT" --apply --force-merged # + delete merged branches whose tip advanced past the PR
"$SCRIPT" --apply --force-gone # + delete GONE branches
"$SCRIPT" --apply --stale --age-days 180 # + delete STALE branches
"$SCRIPT" --apply --remote # + delete matching remote branches after lease check
"$SCRIPT" --apply --prune-tags --gc # + prune listed local tags absent from the remote, reclaim spaceOther flags: to override default-branch detection, to protect extra branches (repeatable), for offline,
to skip GitHub lookups.
--base <branch>--keep '<glob>'--no-fetch--no-ghbash
"$SCRIPT" --apply # SAFE only (merged branches)
"$SCRIPT" --apply --force-merged # + delete merged branches whose tip advanced past the PR
"$SCRIPT" --apply --force-gone # + delete GONE branches
"$SCRIPT" --apply --stale --age-days 180 # + delete STALE branches
"$SCRIPT" --apply --remote # + delete matching remote branches after lease check
"$SCRIPT" --apply --prune-tags --gc # + prune listed local tags absent from the remote, reclaim space其他 flag: 用于覆盖 default 分支检测; 用于保护额外分支(可重复使用); 用于离线运行; 用于跳过 GitHub 查询。
--base <branch>--keep '<glob>'--no-fetch--no-ghGraceful degradation
优雅降级
- No / not authenticated → squash-merge detection falls back to
gh+ ancestor checks; the report says so. Branches squash-merged with their remote still present may land in ACTIVE instead of SAFE. Note this to the user.[gone] - No remote → fetch and are skipped; only local-merged and stale detection run.
gh - Protected worktree: main, dirty, locked, detached, unavailable, and submodule-containing worktrees are kept, as are worktrees with non-disposable ignored files.
- No repository at the current directory → immediate child worktrees are grouped by Git common directory. If none exist, the script exits without acting.
- Base-remote fetch fails (offline, or auth error on the remote that backs
the tiers) → the run continues on local refs and the summary prints . Failures of other remotes (e.g. a dead fork) are ignored and never trip that warning.
⚠ fetch failed — gone/stale tiers computed from possibly-stale local refs - The script is idempotent: re-running after an apply is safe and shows the new state.
- 没有 / 未通过认证 → squash-merge 检测会回退到
gh+ ancestor 检查;报告会说明这一点。远程仍存在的 squash-merged 分支可能会归入 ACTIVE 而不是 SAFE。向用户说明这一点。[gone] - 没有 remote → 跳过 fetch 和 ;仅运行本地 merged 和 stale 检测。
gh - 受保护的 worktree:保留 main、dirty、locked、detached、unavailable 和包含 submodule 的 worktree,也保留含非可丢弃 ignored 文件的 worktree。
- 当前目录不是仓库 → 按 Git common directory 对直接子级 worktree 分组。如果不存在任何 worktree,脚本将退出且不执行操作。
- Base remote fetch 失败(离线,或对支撑各层级的 remote 认证失败)→ 运行会继续使用本地 refs,摘要会打印 。其他 remote 的失败(例如失效的 fork)会被忽略,且不会触发该警告。
⚠ fetch failed — gone/stale tiers computed from possibly-stale local refs - 脚本具有幂等性:apply 后重新运行是安全的,并会显示新状态。
Verification
验证
The dry run is the review gate. Always run it before . After applying,
re-run with no flags; the tiers you acted on should be empty and
protected/active branches and worktrees unchanged. and independently confirm deletions. In container mode,
verify each repository header from the original report; a repository with no
remaining child worktree no longer appears in a later container scan, so run
verification from its recorded Git common directory.
--applygit branch -vvgit worktree list --porcelaindry run 是审查门控。始终应在 之前运行它。应用后,再次不带 flag 运行;已操作的层级应为空,且受保护或处于活动状态的分支和 worktree 应保持不变。 和 可独立确认删除结果。在容器模式下,验证原始报告中每个仓库的标题;不再包含任何子级 worktree 的仓库不会出现在后续容器扫描中,因此应从其记录的 Git common directory 进行验证。
--applygit branch -vvgit worktree list --porcelain