Home / All Skills / Workflow & Core Tools / git-safety-net
Workflow & Core Tools · daymade/claude-code-skills

git-safety-net

Audits, preserves, recovers, and safely retires local Git state: unpushed or wrong-branch commits, dirty or detached worktrees, forgotten duplicate clones of the same repo, untracked work no bundle can back up, orphaned stashes, dangling commits, stale branches, and squash/rebase merge uncertainty. Use when the user fears work was lost; asks to recover a commit or branch; asks whether a worktree, clone, or scratch directory can be deleted; wants everything converged onto one main branch; or needs proof that cleanup will not drop work. Use it even after an audit reported clean — the usual gap is scope: every in-repo command is blind to a second clone elsewhere on disk. Triggers on "did I lose work", "is everything merged", "is anything else lost", "safe to delete this clone", "clean up old branches/stashes", "only keep one main branch", "git reflog", "dangling commits", "分支灾难", "误删分支/commit", "worktree 能删吗", "还有没有丢的东西", "只保留一个主分支". Covers local-Git forensics, not GitHub PR/API operations or routine sync.

L4 High-Privilege · Graded auth & full auditV1 Commit-PinnedExecute CommandInstall DepsNetwork AccessWrite FileDual-pass Audit
Author daymadeGitHub daymade/claude-code-skills ↗Stars 1385License MIT(仓库根 LICENSE 文件;GitHub API spdx MIT;Copyright (c) 2025 daymade)Commit d5c4678cb5
Control levels describe skill capabilities and suggested control measures; they do not represent quality or safety certifications, nor do they dictate usability. Usage decisions rest entirely with users and administrators. Different agent hosts apply varying constraints; do not assume hosts provide automatic protection. Third-party skill copyrights belong to their original authors. Use at your own risk.

1How It Works & Mechanism

The overall architecture consists of an orchestration layer (`SKILL.md`) paired with 6 bundled Bash forensics scripts, all of which are strictly non-destructive and incremental prior to any destructive actions—the recovery process itself must never exacerbate data loss.

git-safety-net/SKILL.md
until a step is explicitly labeled destructive — recovery must never make the loss worse.
What is happening here: Decouples 'reconnaissance/preservation' from 'destruction' into two distinct phases. Scripts only perform read-only enumeration, add refs, and write backup files outside the repository; actual deletions (`stash drop`, `branch -d`, `worktree remove`, retiring clones) are always deferred to the user after evidence and explicit authorization are obtained.

The authoritative check for 'what will I lose?' is executed by `git_loss_audit.sh`: it first runs `fetch` to refresh remote tracking refs, then enumerates the HEAD and status of every linked worktree, local branches/tags, stashes, and dangling commits, exiting with code 1 if any local-only commits or dirty/unreadable worktrees are detected.

git-safety-net/scripts/git_loss_audit.sh
# It refreshes remote-tracking refs with `fetch`, then only inspects repository/worktree state. It
What is happening here: Explicitly accounts for uncommitted files and detached HEADs in other worktrees that `git log HEAD --branches --tags --not --remotes` would overlook (the script uses `git worktree list --porcelain` to collect all HEADs). Exit code semantics are deliberate: dirty or unreadable worktrees block the 'safe to clean' conclusion, whereas stashes and dangling commits are merely reported without triggering a failure.

To guard against 'the audit reports clean, but the work actually lives in another clone': `git_find_all_checkouts.sh` discovers checkouts at the machine level, identifying other checkouts of the same repository by normalizing remote URLs (treating SSH and HTTPS as equivalent) or by matching shared commit history, never by directory name.

git-safety-net/scripts/git_find_all_checkouts.sh
# not `git worktree list`, not `git branch -a`, not `git fsck`, not `git stash list`,
What is happening here: Independent clones possess their own self-contained `.git` directories and lack reverse pointers, rendering them invisible to in-repo inspection tools. The script resolves this by actively searching the entire disk for `.git` entries (directories indicate clones; files denote worktree/submodule gitlinks), running `status`/`rev-list` on candidates while skipping noise paths like `node_modules`, `.venv`, `vendor`, and `.terraform`. This is the skill's primary differentiator.

Merge verification is determined by content-level trial merges rather than commit counting: `git merge-tree --write-tree <base> <branch>` merges the branch into the base in memory. If the resulting tree equals the base tree, it is marked as MERGED (content contained); otherwise, it is flagged as NEEDS REVIEW.

git-safety-net/scripts/git_verify_branch_merged.sh
# 2. Else do a trial 3-way merge of the branch INTO the base (git merge-tree, in memory, no
What is happening here: Squash and rebase merges rewrite SHAs, causing `main..branch` to report hundreds of phantom unmerged commits. The trial merge leverages Git's own internal merge engine to evaluate content containment; script comments and reference docs emphasize that this approach is sound rather than heuristic. On Git versions prior to 2.38 that lack `--write-tree` support, it conservatively falls back to NEEDS REVIEW rather than guessing (reflected by the `MT_RC>=128` branch).

Pre-GC preservation: Pins every dangling commit under the hidden ref namespace `refs/dangling-backup/<sha>`—objects pointed to by a ref are immune to garbage collection and will not pollute `git branch` or `git stash list`.

git-safety-net/scripts/git_preserve_danglers.sh
git update-ref "refs/dangling-backup/$sha" "$sha"
What is happening here: The script restricts itself to read-only Git commands and `git update-ref` to create new refs, strictly avoiding deletions, checkouts, resets, or `gc`. An optional `--patch-dir` exports a `.patch` file for each non-merge commit. Merge and stash commits are identified via parent counts (word count of `rev-list --parents` > 2) because `git format-patch -1` silently emits patches for unrelated commits on merges while exiting with 0—a guardrail to prevent false-positive backup reporting.

Pre-destruction export: Exports stashes as complete binary patches and packages the stash's third parent commit (untracked files captured via `git stash -u/-a`) into a tarball using `git archive "$ref^3"`—because `git stash show -p` ignores these files, relying on patches alone causes silent data loss.

git-safety-net/scripts/git_export_before_drop.sh
# -> stashN-untracked.tar the often-forgotten THIRD parent:
What is happening here: Enforces hard constraints on tool limitations regarding data capture. Branches and full refsets are exported via `git bundle create` (and verified); dangling objects must be pinned before inclusion in an `--all-refs` bundle. The script only writes output files to `--out` and never performs drops or deletions.

Pre-deletion compare-and-swap gate: `--verify-current BUNDLE` compares the refs recorded inside the bundle against the repository's current state one by one, exiting with code 1 if any ref has moved or disappeared.

git-safety-net/scripts/git_export_before_drop.sh
echo "REFSET_CHANGED checked=$CHECKED changed=$MOVED — rebuild and re-verify the bundle before deletion" >&2
What is happening here: Mitigates the risk of ref drift—a branch listing or bundle only proves state at a single moment in time. Deletion actions must immediately follow a fresh re-enumeration and comparison; otherwise, the bundle must be regenerated.

Independent clone retirement preparation: The script audits against an extensive rejection checklist (dirty/untracked/ignored bytes, stashes, reflog-only commits, clone-unique unreachable objects, linked worktrees, local submodules, partial/promisor clones, Git LFS/annex object stores, tracked content filters, `include.path`/`hooksPath` indirections, shallow clones), freezing evidence only after all checks pass.

git-safety-net/scripts/git_prepare_clone_retirement.sh
# It refuses to certify a clone that still has working-tree bytes, ignored files,
What is happening here: A bundle only captures objects known to Git. The script saves ref snapshots, symbolic-ref topologies, reflog OIDs, config/hooks/info file types/modes/hashes, reflog text, repository metadata archives, all-refs bundles, and SHA256 checksums into a freshly created external directory alongside a generated receipt. Runs under `umask 077`, `GIT_NO_LAZY_FETCH=1`, and with fsmonitor disabled (preventing execution of repository-supplied hooks).

Strictly bounded write surfaces: The backup directory must be an absolute path, must not already exist (overwrites are rejected), and must reside entirely outside both the target clone and the surviving repository; the script itself never moves, deletes, or modifies refs.

git-safety-net/scripts/git_prepare_clone_retirement.sh
"$CLONE/"*|"$SURVIVOR/"*) die "backup directory must be outside both repositories" ;;
What is happening here: Codifies the rule of keeping backups outside repositories into programmatic validation, ensuring backups are not inadvertently destroyed alongside the retired directory.

Workflow discipline is embedded in the prompt via 'Outcome contracts + Authorization boundaries': Evidence scope does not equal action scope; authorization is granted per object rather than per repository; preservation and retirement remain strictly phased; and success criteria rely on observable facts in the user's domain (e.g., commit exists on remote, correct branch/worktree states) rather than bundle counts or checksums.

git-safety-net/SKILL.md
- **Evidence scope is not action scope.** A read-only audit may discover another clone, ref,
What is happening here: Pure prompt-level gating combined with `SKILL.md`'s Entry Router (Mode A Recovery / Mode B Audit & Preserve / Mode C Merge Verification / Mode D Prevention / Mode E Safe Retirement) to steer agent behavior. Any newly discovered clone, branch, or worktree is strictly report-only unless explicit user consent is granted.

The script manifest table explicitly annotates the mutation impact of each script (read-only / touches remote-tracking refs only / appends refs only / writes backup files only) and explicitly disclaims authority for any helper to run checkout, reset, push, stash drop, branch -d, or gc.

git-safety-net/SKILL.md
the helpers authorizes `checkout`, `reset`, `push`, `stash drop`, `branch -d`, or `gc`.
What is happening here: Lays out the operational footprint of every script transparently for both the host and the user. Any script that performs a fetch, writes backups, or adds refs requires pre-existing repository coordination to guarantee exclusive write access.

2Core Capabilities

01Machine-level checkout discovery: Locates all independent clones (normalizes SSH/HTTPS URL equivalents, identifies shallow clones via shared commits, and tracks alternates object borrowing)
02In-repo loss auditing: Exhaustively checks local-only commits, dirty states across all worktrees, stashes, and dangling commits, returning exit 1 to block false 'safe to clean' assumptions
03Content-level merge verification: Evaluates branches via ancestor checks or `merge-tree` trial merges, outputting MERGED or UNMERGED-NEEDS REVIEW with a safe bias
04GC-proof preservation: Pins authorized dangling commits under `refs/dangling-backup/*`, with optional per-commit `.patch` export
05Pre-destruction export: Packages selected branches into verified bundles, stashes into binary patches plus third-parent tarballs, and complete ref topologies into all-refs bundles
06Pre-deletion compare-and-swap gating (`--verify-current`): Fails and mandates bundle regeneration if any ref has moved or disappeared
07Zero-loss independent clone retirement preparation: Rejection checklist + ref/symref/reflog/metadata freezing + bundle digest receipts + `READY_TO_QUARANTINE` final verification
08Recovery escalation: Traverses reflog → dropped stashes (including third parents) → detached HEAD → `fsck`, alongside remediation for concurrent shared checkout hazards (foreign commits landing on your branch, staged deletions caused by temporary indexes)
09Flawed probe prevention: Flags counterexamples in `SKILL.md` troubleshooting and evals, such as misleading `ls-remote` file size checks, three-way exit codes in `--is-ancestor`, and empty stash lists hiding autostashes

3External Dependencies

KindDependency / Endpoint
cligit(含 worktree/fsck/reflog/bundle/merge-tree/update-ref/for-each-ref 等)
cligit ≥ 2.38(merge-tree --write-tree 是内容级判定的前提)
cliuv(仅维护者跑回归测试时用到)
clisha256sum / shasum(bundle 指纹;缺失即报错)
clitar(打包 config/hooks/info 元数据)
clistat(跨 BSD/GNU 的 mtime 与文件模式读取)
clilsof(macOS 上探测 clone 是否仍被进程占用;仅文档步骤,不在脚本内)
networkgit fetch(由脚本执行;对远端主机发起出站连接,可能触发宿主 git 凭证助手)
networkgit fetch --all --prune(合并判定脚本执行,同一出站面)
networkgit push(仅文本指导:把 backup 分支推到 origin 做三重备份;无脚本执行)
package无第三方包(Git + 标准 Bash 即可;测试仅用 Python 标准库 unittest/tempfile/subprocess)

4Recommended Governance & Evidence

Suggested Controls for Safe Operation
For Agent Runtime
Graded/per-use authorization, sandbox recommended
For Administrators
Approval workflow, rollback support, full audit
Evidence & Triggers (File Paths & Excerpts)
  • scripts/: Executes local scripts or commands: `git-safety-net/scripts/git_find_all_checkouts.sh` — Read-only: `find` + read-only Git queries (`status`, `rev-list`)
  • scripts/ 或 SKILL.md: Declares dynamic installation of external language package dependencies
  • 网络端点: Declares external network access: Inbound/Outbound: `git fetch "$REMOTE" --prune` (`git-safety-net/scripts/git_loss_audit.sh`)
  • 本地工作目录: File I/O and artifact output: Out-of-repo backups: `git_export_before_drop.sh` defaults to `$HOME/.git-backups/<YYYY-MM-DD>-<repo>/`
Audit Notes: Risk Advisory: Blue (Safe for routine use). Code execution and file writes are present: 6 Bash scripts execute Git commands, write external backups, create hidden refs, and invoke `git fetch` in 3 locations (outbound to remotes, which may trigger host credential helpers). However, destructive capabilities are structurally excluded—scripts do not contain `rm -rf`, `branch -D`, `reset --hard`, `stash drop`, `gc`, or `worktree remove`; all deletions are deferred to the user following explicit approval. File writes are strictly confined outside the repository (refusing to overwrite existing directories, requiring placement outside target/survivor repositories, with `umask 077`). No credentials are read, no third-party APIs are called, and no domains are hardcoded. `SKILL.md` enforces outcome contracts, per-object permissions, single-writer locking, and `verify-current` gates. Residual risks are limited to repository data entering the agent context (prompt injection) and verifying user authorization when executing push/retirement actions per skill instructions—both operational judgment calls rather than script overreach.

5Second-Pass Verification

  • [ok] external_deps 逐条反查调用点:git 系列命令 — 在 6 个脚本里逐条确认 git 子命令的真实执行点(fetch/worktree list/fsck --dangling/stash list/bundle create+verify/list-heads/reflog/for-each-ref/update-ref/check-attr/submodule status/cat-file/rev-list)。全部为执行路径上的真实调用,非注释。
  • [ok] external_deps:uv 与 lsof 是否真在脚本里 — 两者都不在脚本中执行:`uv run python -m unittest discover -s tests -p 'test_*.py'` 只出现在 SKILL.md § Maintainer verification(维护者本地跑测试);lsof 只出现在 references/merge_verification.md 的退役 READ-DO 序列(macOS 探测进程占用)。已按『文档层工具』而非『运行时依赖』归类。
  • [ok] 网络调用面是否存在遗漏(隐藏脚本/混淆内容) — glob 全量(hidden=true, gitignore=false)显示该 skill 目录仅 17 个文件:SKILL.md、3 个 references、6 个 scripts、6 个 tests、evals/evals.json、agents/openai.yaml,无可执行二进制、无压缩/混淆内容。全目录 grep curl/wget/gh/nc/python -c 零命中;唯一 https:// 出现在 find_all_checkouts 的 URL 归一化注释示例里。
  • [ok] 反例排查:git_find_all_checkouts.sh 号称不联网,但脚本里有 `git fetch --all --prune` — 该行(第 317 行)位于 `cat <<'FRESHNESS'` heredoc 内,是打印给用户看的建议,不在执行路径上;脚本头部 `# NON-DESTRUCTIVE: runs only \`find\` plus read-only Git queries` 与代码一致(唯一外部命令是 find 与只读 git 查询)。不构成 discrepancy,因此改为标注为『文本指导』。
  • [ok] 反查『脚本非破坏性』是否属实(是否有删除/改写仓库对象) — 对 rm -rf / branch -D / reset --hard / stash drop / worktree remove / update-ref -d / gc 全目录扫描:脚本内仅两处相关文本——preserve_danglers 的 `rm -f "$OUT"`(删除自己刚写失败的 patch 文件)与 loss_audit 的提示字符串 `never use 'git worktree remove --force'`。所有真正的破坏性命令(`git update-ref -d`、`git worktree remove`、`--force-with-lease` 等)只出现在 SKILL.md/references 供人执行的步骤中。
  • [ok] 『写操作面』核对:备份到底写到哪里、是否会覆盖既有数据 — export 脚本默认写 $HOME/.git-backups/<date>-<repo> 并可 --out 覆盖;preserve_danglers 的 --patch-dir 先绝对化再 mkdir -p;prepare_clone_retirement 强制 `[ ! -e "$OUT" ]`(拒绝已存在目录)、要求绝对路径、并 `case "$OUT/" in "$CLONE/"*|"$SURVIVOR/"*) die ...` 拒绝把备份放进被退役/保留的仓库内。三处均与 SKILL.md『备份放仓库外』一致。
  • [ok] 凭证/全局配置读取面反查 — 全目录 grep --global / .gitconfig / credential / HOME 的结果:脚本内只有 export 的 `$HOME/.git-backups/...` 默认输出路径;`git config --global` 只出现在两处 references 中作为给用户的建议命令。prepare_clone_retirement 读取仓库私有配置时显式用 `git config --file <config> --no-includes`(不吞并用户全局配置)。无 token/env 读取。
  • [ok] 实现原理是否夸大:『内容级判定是 sound 而非启发式』 — 与脚本逐行比对成立:脚本先 `git merge-base --is-ancestor` 判 ancestor,再 `git merge-tree --write-tree <base> <branch>` 比较结果树与 base 树;MT_RC>=128(git<2.38)时明确退回 NEEDS REVIEW 而非猜 MERGED。声明与实现一致,未夸大。

6Verdict & Scenarios

  • Solves audit blind spots as a first-order problem: Independent clones are invisible to in-repo tools, so it includes machine-level checkout discovery scripts that normalize remote URLs and identify shared commit histories rather than relying on directory names.
  • Uses Git's native trial merge instead of heuristics, intentionally adopting a safe bias: marks state as MERGED only when content containment is proven, leaving everything else for human review.
  • Architecturally decouples destruction from preservation: Scripts strictly perform read-only queries, ref additions, or out-of-repo writes; hidden bytes like the third parent of a stash have dedicated export paths, and untracked files are explicitly flagged as existing solely on disk.
  • Enforces robust deletion gates: Uses compare-and-swap (`--verify-current` / `REFSET_CHANGED`) and final retirement verification (`READY_TO_QUARANTINE` + sha256 receipts) to turn dynamic ref volatility into concrete programmatic checks.
  • Production-grade engineering: Backed by 6 scripts with 1,730 lines of behavioral regression tests, 8 evaluation cases codifying operational discipline, and section-indexed reference documentation (§) loaded on demand to handle 84KB of background material.
  • Explicit concurrency and authorization model: Enforces single-writer execution, per-object authorization, and inspect-only vs. change-authorized workflows, featuring executable detections for shared checkout hazards (foreign commits on local branches, staged deletion traps from temporary indexes).
  • Best for: Ideal for: Developers who have experienced or fear local Git data loss ('did I lose a commit?', 'can I safely delete these worktrees/stashes/branches?', 'is this actually merged into main?', 'how many copies of this repo exist on this machine?'); teams seeking to establish write permissions and evidentiary discipline across shared multi-agent/multi-session checkouts; and skill authors looking to adopt the 'non-destructive forensics scripts + authorization gates' pattern. Best deployed by running audit and preservation before cleanup, reserving deletions for an entirely separate phase.
    Not for: Not suitable for: Workflows requiring GitHub PR/API operations (explicitly delegated to other skills, with routine push/sync handled by `/auto-repo-setup`); users looking for a one-click automated sweep who reject a cautious 'prove before deleting' process; repositories backed by promisor/partial clones, Git LFS/annex dependencies, or tracked content filters during clone retirement (which scripts will actively reject); or scenarios expecting the skill to autonomously perform destructive deletions or modify global Git configuration.
    Install Agent-Ready
    ① Verified Mirror 2026-09-15
    Option A · Direct DownloadDownload git-safety-net.tar.gz
    sha256: b2b944f8a078459b…
    Option B · Copy Guide for Agent
    install.json
    Agents automatically download and verify mirrors from this JSON guide.
    ② Upstream GitHub
    GitHub Repo ↗
    Pinned to commit d5c4678cb5.