基础工具与工作流 · 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.

风险提醒:蓝色 · 知晓即可AI 侦查报告
作者 daymadeGitHub daymade/claude-code-skills ↗Stars 1385许可 MIT(仓库根 LICENSE 文件;GitHub API spdx MIT;Copyright (c) 2025 daymade)commit d5c4678cb5
agent 宿主通常会约束 skill 执行权限;风险提醒为 AI 侦查观点,不构成质量或安全保证。第三方 skill 仅作拆解与展示,安装使用风险自负,版权归原作者。

1实现原理 · 为什么它能做到

整体定位是『编排层 SKILL.md + 6 个自带 bash 取证脚本』,且所有脚本在破坏动作前一律非破坏性/增量式——恢复动作本身绝不能让损失更大。

git-safety-net/SKILL.md
until a step is explicitly labeled destructive — recovery must never make the loss worse.
注:这里在做什么:把『侦查/保全』与『销毁』分成两相。脚本只做只读枚举、加 ref、写仓库外备份文件;真正的删除(stash drop / branch -d / worktree remove / 退役 clone)永远留给用户在拿到证据与授权后执行。

『我会丢掉什么』的权威检查由 git_loss_audit.sh 实现:先 fetch 刷新远端跟踪 ref,再枚举每个 linked worktree 的 HEAD 与 status、本地分支/标签、stash、dangling commit,任何本地独有 commit 或脏/不可读 worktree 会 exit 1。

git-safety-net/scripts/git_loss_audit.sh
# It refreshes remote-tracking refs with `fetch`, then only inspects repository/worktree state. It
注:这里在做什么:把 `git log HEAD --branches --tags --not --remotes` 会漏掉的『另一个 worktree 里的 detached HEAD』和『未提交文件』显式纳入(脚本用 `git worktree list --porcelain` 收集全部 HEAD)。退出码语义是刻意的:dirty/不可读 worktree 阻塞『可安全清理』的结论,而 stash/dangling 只报告不失败。

防『审计干净但东西其实在另一个 clone 里』:git_find_all_checkouts.sh 做机器级 checkout 发现,靠规范化 remote URL(SSH/HTTPS 等价)或『共享任一 commit 历史』来识别同一仓库的其他 checkout,从不按目录名匹配。

git-safety-net/scripts/git_find_all_checkouts.sh
# not `git worktree list`, not `git branch -a`, not `git fsck`, not `git stash list`,
注:这里在做什么:独立 clone 有完整 .git、没有反向指针,因此对所有 in-repo 工具都不可见——脚本因此自己 find 全盘的 .git(目录=clone、文件=worktree/submodule gitlink),并对候选执行 status/rev-list 并跳过 node_modules/.venv/vendor/.terraform。这是本 skill 最核心的差异化能力。

合并判定不数 commit,而是做内容级试验合并:`git merge-tree --write-tree <base> <branch>` 在内存里把分支合回 base,若结果树 == base 树则判 MERGED (content contained),否则 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
注:这里在做什么:squash/rebase 合并会重写 SHA,`main..branch` 于是显示 100+ 个『未合并』幽灵提交;试验合并用 Git 自己的合并机制判定内容包含,脚本注释与 references 都强调这是 sound 而非启发式。git < 2.38 不支持 --write-tree 时保守退回 NEEDS REVIEW 而不是猜『已合并』(可见脚本中 MT_RC>=128 分支)。

gc 前保全:把每个 dangling commit 钉在隐藏 ref 命名空间 refs/dangling-backup/<sha> 下——有 ref 指着的对象永不被 gc 回收,且不会污染 `git branch`/`git stash list`。

git-safety-net/scripts/git_preserve_danglers.sh
git update-ref "refs/dangling-backup/$sha" "$sha"
注:这里在做什么:脚本自称只跑只读 git 加 `git update-ref` 新增 ref,绝不删 ref/checkout/reset/gc。可选 --patch-dir 为每个非 merge 提交导出 .patch;用父提交个数(rev-list --parents 词数 >2)判断 merge/stash,因为 `git format-patch -1` 对 merge 会静默产出别的提交的 patch 且 exit 0——这是防『备份写错还报成功』的细节。

销毁前导出:stash 导出为完整二进制 patch,并额外用 `git archive "$ref^3"` 把 stash 的第三父提交(`git stash -u/-a` 携带的未跟踪文件)打成 tar——因为 `git stash show -p` 不显示这些文件,只导 patch 会静默丢失它们。

git-safety-net/scripts/git_export_before_drop.sh
# -> stashN-untracked.tar the often-forgotten THIRD parent:
注:这里在做什么:把『哪些备份工具根本够不到哪些工作』做成硬约束。分支/全 ref 走 `git bundle create`(并 verify),dangling 对象必须先 pin 才能进 --all-refs bundle。脚本只写文件到 --out,自身不做 drop/delete。

删除前的 compare-and-swap 门禁:`--verify-current BUNDLE` 逐条比对 bundle 里记录的 ref 与仓库当前值,任何 ref 移动/消失即 exit 1。

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
注:这里在做什么:回应『ref 集合本身会动』这条轴——分支清单与 bundle 只证明某一瞬间的状态;删除动作必须紧跟在重新枚举+比对之后,否则要重建 bundle。

独立 clone 退役准备:脚本先按一长串拒绝清单核查(脏/未跟踪/ignored 字节、stash、reflog-only commit、clone 独有不可达对象、linked worktree、本地 submodule、partial/promisor clone、Git LFS/annex 对象库、tracked content filter、include.path/hooksPath 间接层、浅克隆),全部通过才冻结证据。

git-safety-net/scripts/git_prepare_clone_retirement.sh
# It refuses to certify a clone that still has working-tree bytes, ignored files,
注:这里在做什么:bundle 只能证明『git 已知的对象』。因此它把 ref 快照、symbolic-ref 拓扑、reflog OID、config/hooks/info 的类型+模式+哈希、reflog 文本、仓库元数据 tar、all-refs bundle 与 sha256 写进一个新建的外部目录,并生成 receipt;umask 077、GIT_NO_LAZY_FETCH=1、禁用 fsmonitor(防 repo 提供的命令被执行)。

写操作面被硬性限制:备份目录必须是绝对路径、必须不存在(拒绝覆盖)、必须在 clone 与 survivor 两个仓库之外;脚本自身从不移动/删除 checkout、从不改 ref。

git-safety-net/scripts/git_prepare_clone_retirement.sh
"$CLONE/"*|"$SURVIVOR/"*) die "backup directory must be outside both repositories" ;;
注:这里在做什么:把『备份放仓库外』从纪律条款变成代码校验,避免备份随被退役的目录一起被删。

工作流纪律以『Outcome contract + 授权边界』写进 prompt:证据范围 ≠ 行动范围,授权是按对象而非按仓库的,保留/退役分相,完成标准用用户世界的可观测事实(远端已有该 commit、分支/worktree 状态正确)而非 bundle 数量或校验和。

git-safety-net/SKILL.md
- **Evidence scope is not action scope.** A read-only audit may discover another clone, ref,
注:这里在做什么:这是纯 prompt 层的门禁,配合 SKILL.md 的 Entry router(Mode A 恢复 / B 审计保全 / C 合并核验 / D 预防 / E 安全退役)决定 agent 该走哪条路;无用户显式授权时新发现的 clone/branch/worktree 一律 report-only。

脚本清单表逐条标注『是否变更』(read-only / 只动 remote-tracking refs / 只加 refs / 只写备份文件),并声明所有 helper 都不授权 checkout、reset、push、stash drop、branch -d、gc。

git-safety-net/SKILL.md
the helpers authorizes `checkout`, `reset`, `push`, `stash drop`, `branch -d`, or `gc`.
注:这里在做什么:用表格把每个脚本的变更面摊开给宿主与用户看;任何 fetch/写备份/加 ref 的脚本都要求先通过仓库既有协调机制取得独占写权。

2核心能力

01机器级 checkout 发现:找出所有独立 clone(含 SSH/HTTPS 等价 URL 归一、浅克隆按共享 commit 识别、alternates 借库标记)
02仓库内损失审计:本地独有 commit / 每个 worktree 的脏状态 / stash / dangling commit 一次列全,exit 1 阻塞『可安全清理』结论
03内容级合并判定:ancestor 或 merge-tree 试验合并,输出 MERGED / UNMERGED-NEEDS REVIEW 且安全偏置
04gc-proof 保全:把授权范围内的 dangling commit 钉到 refs/dangling-backup/*,可选每提交导出 .patch
05销毁前导出:选中分支进 verified bundle、stash 进二进制 patch + 第三父提交 tar、全 ref 拓扑进 all-refs bundle
06删除前 compare-and-swap 门禁(--verify-current):ref 移动/消失即失败并要求重建 bundle
07独立 clone 无损失退役准备:拒绝清单 + ref/symref/reflog/metadata 冻结 + bundle 摘要 receipt + READY_TO_QUARANTINE 终检
08恢复阶梯:reflog → dropped stash(含第三父)→ detached HEAD → fsck,以及共享 checkout 并发事故(外部 commit 落到你的分支、临时 index 造成的 staged deletion 陷阱)的处置
09阻止『用错的探针』:ls-remote 文件大小判定、--is-ancestor 三种退出码、stash list 空 ≠ 没 stash(autostash)等反例被写进 SKILL.md troubleshooting 与 evals

3外部依赖

类型依赖
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)

4风险提醒 风险提醒:蓝色 · 知晓即可

风险提醒:蓝色 · 知晓即可
  • 需执行真实 shell 脚本,且脚本会对远端发起 git fetch(出站网络 + 可能触发宿主凭证助手)。 — loss_audit 与 verify_branch_merged 都会 fetch;在共享/多写者 checkout 中,fetch 会移动 remote-tracking refs——SKILL.md 为此要求先转移独占写权,否则只能保持只读并声明『合并判定不可用』。执行前应确认目标仓库与 remote 身份是你预期的那个。
  • 会被审计仓库的内容进入 agent 上下文(提示注入面)。 — 分支名、stash 消息、commit subject、文件路径都会打印并被模型读取;恶意仓库可借此注入指令。脚本有部分加固(禁用 repo 提供的 fsmonitor、GIT_NO_LAZY_FETCH、stash 消息清洗为文件名、`--` 防 pathspec 混淆),但这不是通用注入防御;宿主应对输出保持数据/指令分离的处置。
  • 『非破坏性』是脚本层的保证,不是整个 skill 的保证。 — SKILL.md 会引导执行真正的破坏性步骤(rebase --onto 修历史、update-ref -d 撤销 pin、git worktree remove、stash drop、branch -d/-D),这些命令不在脚本里,风险由执行者与授权门禁承担。
  • 退役脚本的『无损失』有明确能力边界,容易被误读为全量保证。 — Git LFS/annex 对象库、tracked content filter、include.path/hooksPath 间接层、promisor/partial 克隆、浅克隆、本地 submodule 均被拒绝并要求人工单独审计——即遇到这些状态脚本会直接失败,而不会替你保住那些字节。
  • 默认备份位置在 $HOME/.git-backups,且 references 建议改用户全局 git 配置(gc.reflogExpire / gc.reflogExpireUnreachable)。 — 备份目录若被用户清理策略覆盖会失去意义(SKILL.md 要求把备份放在仓库外并写 README 说明来源);`git config --global` 会修改用户 ~/.gitconfig,属文档级建议,需用户自行判断。
  • 证据只对 pin 的 commit 有效,且 skill 体量与纪律密度很高。 — 本报告针对 commit d5c4678cb5d4fd6acc9c922690df035dbd33d247(仓库 CHANGELOG 显示 git-safety-net 迭代到 v1.17.0,条款仍在快速增补);SKILL.md 58KB + references 85KB 的规约密度意味着使用者(或 agent)可能只执行到部分条款,导致『按 skill 走却漏了门禁』。
风险提醒:蓝色,正常使用。真实存在代码执行与写入:6 个 bash 脚本会跑 git 命令、写仓库外备份、新增隐藏 ref,并有 3 处会执行 `git fetch`(对远端出站,可能触发宿主凭证助手)。但破坏面被结构性排除——脚本本身不含 rm -rf / branch -D / reset --hard / stash drop / gc / worktree remove,删除动作全部留给用户在显式授权后执行;写操作面被硬约束在仓库外目录(拒绝覆盖已存在目录、必须在 clone/survivor 之外、umask 077);无凭证读取、无第三方 API 与无硬编码域名;且 SKILL.md 有 outcome contract、按对象授权、单写者与 verify-current 等门禁。真正的残余风险是『读到的仓库内容进入 agent 上下文』(提示注入)与『按 skill 指引执行 push/退役动作时操作者是否真有授权』,属使用层面的判断,而非脚本越权。

5第二遍独立确认

  • [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。声明与实现一致,未夸大。

6结论

  • 把『审计盲区』当第一性问题解决:独立 clone 对所有 in-repo 工具不可见,因此自带机器级 checkout 发现脚本,并按 remote URL 归一或共享 commit 历史识别(不靠目录名)。
  • 合并判定用 Git 自己的试验合并而非启发式,并显式接受『安全偏置』:只有证明内容被包含才给 MERGED,其余一律交人复核。
  • 破坏与保全在架构上分离:脚本只会只读、加 ref 或写仓库外文件;stash 的第三父提交这类『patch 看不到的字节』有专门导出通道,未跟踪文件则被明确指出『只有磁盘那一份』。
  • 有真正的删除门禁:compare-and-swap(--verify-current / REFSET_CHANGED)与退役终检(READY_TO_QUARANTINE + sha256 receipt),把『ref 集合会动』变成可执行检查。
  • 工程化程度高:6 个脚本配 1730 行行为级回归测试,8 条 evals 锚定纪律条款,references 用 § 段落索引按需加载(应对 84KB 参考体量)。
  • 并发/授权模型显式化(one writer、按对象授权、inspect-only vs change-authorized),并把共享 checkout 的两种真实事故(他人 commit 落到你分支、临时 index 造成的 staged deletion)写成可执行检测。
  • 适合:适合:本地 Git 出过或担心出事的人——『我是不是丢了 commit』、『这些 worktree/stash/分支能不能删』、『是不是真的都合进 main 了』、『机器上到底有几个这个仓库的副本』;也适合需要在多 agent/多会话共享 checkout 的环境里建立写权与证据纪律的团队;以及想照抄『非破坏性取证脚本 + 授权门禁』模式的 skill 作者。首选场景是动手清理之前跑一次审计与保全,删除动作另起一相。
    不适合:不适合:需要 GitHub PR/API 侧操作(SKILL.md 明确划归其他 skill,日常提交推送交给 /auto-repo-setup);只想一条命令自动清干净而不接受『先证明再删』的慢流程的人;处于 promisor/partial clone、Git LFS/annex 依赖或带 tracked content filter 的仓库上做 clone 退役(脚本会直接拒绝);期待 skill 自动替你做破坏性删除或自动改 git 全局配置的场景。
    安装 agent 直装可复制
    ① 本站镜像 更新 2026-09-15
    方式 A · 人下载镜像包下载 git-safety-net.tar.gz
    sha256: b2b944f8a078459b…
    方式 B · JSON 格式安装指南,复制给 agent
    安装指南
    agent 读 JSON 指南后会自动从本站下载安装,无需更多说明。
    ② 上游 GitHub · 原始来源
    能访问 GitHub?直接去上游安装(实时版,可能已更新)GitHub 原始 ↗
    本页镜像锁定 commit d5c4678cb5;上游为实时仓库。
    来源信息 GitHub 原始
    作者 / 仓库daymade / daymade/claude-code-skills
    Stars1385
    最近推送2026-09-09
    本 skill commitd5c4678cb5
    许可MIT(仓库根 LICENSE 文件;GitHub API spdx MIT;Copyright (c) 2025 daymade)
    本站信息
    收录日期2026-09-06
    分类基础工具与工作流
    侦查报告AI 侦查 · 2 遍 · 2026-09-06
    本站镜像与 GitHub 原始是不同来源:本站锁定 commit 快照经 /r2 分发;GitHub 为实时上游,内容可能已更新。
    同分类邻近