关于 re0-squash
re0-squash 是一项需人工明确调用的技能,用于将 GitHub 仓库历史压缩为一个签名提交,并删除后重建远程仓库。它保留相同文件树,但会逐项审计远程数据损失,并要求人工确认后才执行不可逆删除。
主要功能
- 01审计本地状态、远程内容与设置
- 02将历史压缩为单个签名提交
- 03生成并验证旧历史 bundle
- 04删除并重建 GitHub 远程仓库
- 05检查推送结果与设置漂移
适用场景
- 01清理仓库提交历史并重新发布
- 02评估删除远程仓库会丢失的内容
- 03将旧历史保存在本地 bundle 中
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ lilmgenius/ paperthin --skill re0-squash安装后在 Claude Code 中输入/re0-squash确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
agents/openai.yamlscripts/squash.mjssquash.test.mjs详细介绍
将一个仓库的历史压缩为一个签名提交,并保留相同的树;然后删除其 GitHub 远程仓库,按脚本记录的设置(步骤 4)重新创建,并推送该提交。
目标
强制推送不会清除 GitHub 历史记录。GitHub 关于删除敏感数据的指南指出,重写的提交仍可能通过克隆和复刻保持可访问,也可能通过缓存视图中的哈希,以及引用这些提交的拉取请求继续被访问。删除仓库才能从中移除这些对象,因此此技能会将每个提交压缩为一个,删除远程仓库,按可恢复的设置重新创建仓库,并推送这一个提交。树保持逐字节相同;只有记录会改变。
这不是重新开始:不会重建任何内容,也不会在远程仓库上保留存有旧历史的归档分支。从 v0 重新开始可使用 re0-work。
此操作由用户主动调用:它会删除远程仓库,且无法撤销;触发操作的是用户的明确行为,而触手可及的模型也可能自行执行删除。只有当用户点名此技能,或要求压缩仓库历史并重新创建其远程仓库时,才运行它。
工作流
前提条件:已配置提交签名的 git,以及已通过包含 delete_repo 权限范围的 gh 进行身份验证。--repo 可覆盖从 origin 读取的所有者/名称。
输入包括:默认分支上的干净检出、用户批准的提交消息,以及用户对审计列出的每项损失的接受。一个打包脚本通过三个子命令完成工作,需在仓库根目录中运行(即将重新发布的仓库根目录;下方的 scripts/squash.mjs 指此技能文件夹中的脚本,调用时需使用其绝对路径):
node scripts/squash.mjs audit [--repo <owner/name>]
node scripts/squash.mjs squash --message-file <file> [--bundle <path>]
node scripts/squash.mjs republish --confirm <owner/name> [--accept-loss] [--repo <owner/name>]
每个子命令都会输出一个 JSON 对象。退出码:0 表示完成(audit:没有阻塞项;republish:推送的 head 匹配且设置未发生偏差);1 表示已拒绝或失败(工作树不干净、处于分离 HEAD 状态、--confirm 错误、未接受阻塞项、提交数超过一个、git 或 gh 调用失败、推送的 head 不匹配,或恢复的设置发生偏差);2 表示用法错误;3 表示审计发现阻塞项。
- 审计。 在检出目录中运行
node scripts/squash.mjs audit [--repo <owner/name>]。其 JSON 会列出本地状态(local)、删除操作会移除的所有远程项目(remote)、重新发布时会恢复的设置(settings)、blockers和notes。阅读每一项阻碍;如果无法读取某个远程列表,这本身就是一项阻碍,因为无法排除其中的内容会丢失。公开 fork 会在删除后保留旧提交,但此技能无法处理它。停止:由人工决定。 向人工说明每一项阻碍,并由他们逐项接受或拒绝损失;只要拒绝一项损失,就到此结束,什么都不会被压缩。提出压缩请求,不代表接受一项尚未告知的损失。 - 撰写消息。 如果人工希望压缩消息遵循仓库中现有提交消息所采用的规范,请告知他们在此步骤前运行
/re0-git;该命令由用户调用,因此此技能绝不会调用它。先阅读仓库记录的提交规范和提交日志。撰写一条主题,说明仓库是什么;空一行;然后每项持久能力各写一条-项目符号,在单行中说明它现在的用途,不要换行。省略流程历史、回滚和重命名,因为压缩操作会舍弃这些内容;也不要添加共同作者尾注。停止:由人工决定。 压缩前向人工展示消息,只有获得批准后才能压缩;然后将批准的消息保存到文件中。 - 压缩。 在干净的检出目录中运行
node scripts/squash.mjs squash --message-file <file> [--bundle <path>]。该命令会将旧历史写入经过验证的 bundle(除非--bundle指定路径,否则保存在主目录中);远程内容删除后,这是你持有的旧历史唯一副本。它会将分支替换为一条树相同、已签名且日期为当前的提交;其 JSON 会给出旧 tip(old)、新提交(new)、commits、signature和bundle。除非commits为 1 且signature为G,否则停止:该脚本不会检查签名,未签名或包含多条提交的结果不得重新发布。 - 重新发布。此步骤会删除 GitHub 仓库,且删除后无法撤销。 审计列出的每个远程项目都会随之删除。从此时起,第 3 步生成的 bundle 是你持有的旧历史唯一副本;fork 和其他克隆仍会保留旧历史,但此技能无法处理它们。停止:由人工决定。 只有当人工在本次对话中明确要求删除,并指出此仓库的 owner/name 时,才可以删除。为确认人工对仓库及删除所涉损失的理解,请使用 owner/name 和已接受的损失列表调用 Skill 工具并传入 "readback";只有人工确认复述无误后才可删除。再次运行
node scripts/squash.mjs audit,并将其阻碍与人工已接受的阻碍进行比较,因为重新发布时会再次审计,但使用--accept-loss会让新出现的阻碍未被告知便通过;如有新阻碍,必须交由人工处理。然后运行node scripts/squash.mjs republish --confirm <owner/name> [--accept-loss] [--repo <owner/name>],其中--confirm必须原样重复 owner/name,只有人工接受了每一项阻碍时才可使用--accept-loss。该命令会再次审计、删除并重新创建仓库、恢复已记录的设置,并将那一条提交推送为默认分支;其 JSON 会给出已推送的 head(pushed)、matchesLocal、发生偏差的设置(settingsDrift)、未恢复的内容(notRestored)以及ok。 - 收尾。 监看首次 CI 运行;如果失败或始终未启动,连同其日志一并报告,并将重新发布视为未完成。告知人工 bundle 的位置、它是他们持有的旧历史唯一副本且会一直保留到他们删除为止;告知
secrets、variables、webhooks、rulesets、deploy keys和collaborators均未恢复,如需保留,必须手动重新创建;并告知每个其他克隆都必须先运行git fetch和git reset --hard origin/<branch>,之后才能再次推送。 当审计发现人类不接受的阻碍项,或人类在任一暂停点拒绝继续时,不会压缩提交,也不会删除任何内容:报告审计结果并停止。这属于成功运行。
规则
- 除非在本次对话中收到明确请求,且请求中点名此仓库,否则绝不删除远程仓库。
--confirm必须原样重复 owner/name。 - 不得代替人类接受任何损失。只有在人类已在本次对话中接受所有列出的阻碍项后,才可传入
--accept-loss。 - 只重新发布一个分支。其他本地分支和标签保留旧提交,且不会被推送。
- 压缩提交的日期设为当前时间,并经过签名;它记录重新发布的时间。内容绝不改变:旧提交顶端与新提交之间的
git diff为空。 - 任何步骤失败都会停止运行。推送后的提交与预期不一致,或设置发生漂移,都必须报告为失败,绝不能报告为完成。
验证
- 已运行审计,且每一项阻碍都已向人类说明,并在人类接受后才重新发布。
- 旧提交顶端与新提交之间的
git diff <old> <new>为空,该分支只包含一个提交,且签名状态为G。 - 归档包已存在且通过验证(
git bundle verify <bundle>)。 - 重新发布的输出显示
matchesLocal为 true、settingsDrift为空、ok为 true,且首次 CI 运行通过。 - 已告知人类归档包路径、未恢复的内容,以及其他克隆副本的恢复方法。