惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

U
Unit 42
Google DeepMind News
Google DeepMind News
Stack Overflow Blog
Stack Overflow Blog
H
Help Net Security
MongoDB | Blog
MongoDB | Blog
I
InfoQ
N
Netflix TechBlog - Medium
T
Tailwind CSS Blog
量子位
博客园 - 叶小钗
月光博客
月光博客
IT之家
IT之家
G
Google Developers Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
小众软件
小众软件
S
SegmentFault 最新的问题
Engineering at Meta
Engineering at Meta
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
aimingoo的专栏
aimingoo的专栏
云风的 BLOG
云风的 BLOG
Vercel News
Vercel News
爱范儿
爱范儿
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
宝玉的分享
宝玉的分享

暗无天日

读:AI Agent 安全日志——从可见性与隐私的两难说起 - 暗无天日 读:AI Agent 生产化——一份从原型到上线的速查清单 - 暗无天日 AI写作的语言指纹——如何让文字不那么像机器 - 暗无天日 读:50 条 Claude Code 技巧——一个工程经理的六个月使用心得 读:AI 辅助开发为什么让 E2E 测试更有价值 - 暗无天日 读:在Emacs中使用Claude Code(Spacemacs适配版) - 暗无天日 Claude Code 背后的工程哲学——读 Agent Harness Engineering 读:Agent Harness Engineering——AI 智能体不只是模型,还有套件 - 暗无天日 browser-harness:让 AI 直接接管你的浏览器 - 暗无天日 读:Security-First CI/CD —— DevSecOps 自动化实践指南 TIL: 数字小键盘的小数点陷阱与行内算术求值 - 暗无天日 读:Immutability 不是万能药,它是一种权衡 - 暗无天日 Conducty:给 Claude Code 加上项目记忆和并行执行能力 - 暗无天日 读 — GitHub Trending 里的 Claude Code 技能包 读 — Prompt Caching 省钱指南 TIL: Emacs 中那些跟鼠标配合的冷门快捷键 - 暗无天日 读:Anvil——把 Emacs 变成 AI 的工具服务器 读:Emacs 代码折叠终极指南 - 暗无天日 读:Clojure 搭车客指南 - 暗无天日 多智能体系统的两个有效模式——以及对 Claude Code 用户的启示 - 暗无天日 用 Org Babel 写 Literate 博文:扩展执行 + 定制导出 proced:Emacs 内置的进程查看器 - 暗无天日 从 proced 定制中学到的 Elisp 模式 读:让 Emacs proced 在 macOS 上显示 CPU 和内存 异步编程的函数着色税 - 暗无天日 链式调用的代价:JavaScript 和 Clojure 的共同教训 - 暗无天日 hyperfine:命令行基准测试工具 - 暗无天日 管道中的变量去哪了?——子 shell 作用域陷阱 - 暗无天日 开源包装器的信任陷阱:四个危险信号 - 暗无天日 程序员愿意为 AI 写文档,却不愿为同事写 - 暗无天日
git推送失败后恢复仓库损坏的完整记录 - 暗无天日
2026-04-26 · via 暗无天日

虽然 filter-branch 已经重写了历史,但旧的损坏对象仍然以"松散对象"(loose object)的形式留在硬盘上。这些对象不被任何分支引用,但 git 仍能看到它们并报错。

具体来说,补齐缺失对象后 git gc 仍然报错。运行 git fsck 检查,报错的内容变了——不再是缺少 =4de66b3=,而是:

损坏的链接来自于 tree ab43ad01 → tree d0c6a58
缺失 tree d0c6a58

这说明 d0c6a58 这个 tree 仍在硬盘上,且它引用的子 tree 本来应该是 4de66b3=(就是之前缺失的那个),但现在这个引用关系断裂了。由于 =d0c6a58 本身还是一个可读的对象,它就成了新的"损坏源头"。

检查它是不是松散对象:

$ ls .git/objects/d0/c6a58cd6ccac7e967a1ec1923b86b6098c37cf
.git/objects/d0/c6a58cd6ccac7e967a1ec1923b86b6098c37cf

文件存在,说明它是松散对象。注意路径的规律:git 取对象哈希的前两个字符 d0 作为目录名,后 38 个字符作为文件名。这样每个目录下最多只有 256 个文件(00~ff),避免单个目录的文件数量爆炸。再检查它是否还被当前分支引用:

$ git rev-list --objects main | grep d0c6a58
# (无输出)

无输出,说明 main 分支已经不需要它了。=rev-list –objects main= 的作用是遍历 main 分支能到达的所有对象(包括提交、目录树、文件),逐一列出它们的哈希。如果目标哈希出现在这个列表里,说明某个提交还用着它,删了会破坏历史。没输出就说明安全,可以删。

确认安全后删除:

$ rm -f .git/objects/d0/c6a58cd6ccac7e967a1ec1923b86b6098c37cf

然后重复这套流程——再跑 =git fsck=,看下一层是谁:

损坏的链接来自于 tree b46bf016 → tree ab43ad01
缺失 tree ab43ad01

这次 ab43ad01 浮出来了。它被另一个 tree 引用,自身也是个松散对象。

ls .git/objects/ab/43ad01abfddc06d9ae24d81d9fe96a8007e3dd  ✓ 存在
git rev-list --objects main | grep ab43ad01  ✓ 不被 main 引用

删掉它:

$ rm -f .git/objects/ab/43ad01abfddc06d9ae24d81d9fe96a8007e3dd

如此反复,每删一层就跑 git fsck 看上一层,直到 git fsck 不再报错。

总结这个"顺藤摸瓜"的过程:

  1. git fsck 告诉你哪个对象是"损坏的链接"的源头
  2. git rev-list --objects main | grep <哈希> 确认不被任何分支需要
  3. ls .git/objects/xx/xxx... 确认它是松散对象
  4. 删除,回到第 1 步

注意这里的删除用的是直接 rm -f 删文件,而不是用 git 命令。因为松散对象就是硬盘上实实在在的文件,直接删掉文件系统层面的文件就可以了。但对于 reflog、分支引用这类 git 的"元数据",就要用 git 提供的命令(如 git reflog expire=)来操作,不能直接去删 =./git/ 里的文件。 #+END_EXAMPLE