Git 对象损坏 loose object corrupt 速查:fsck 定位与恢复
更新时间:2026-10-24。FAQ 速查页,面向
git status/git log突然报loose object is corrupt、或者任何 git 命令都以fatal退出的同学。Git 对象损坏的本质是.git/objects/里的某个对象文件(blob/tree/commit/tag 之一)内容与它自己的 SHA-1 对不上账:读出来解压、算一遍哈希,发现不是文件名上那个数,git 就拒绝继续。常见诱因集中在六个:磁盘坏块或文件系统错误、异常关机/断电导致对象只写了一半、手动杀进程留下残文件、清理脚本误删.git内容、磁盘写满时 commit 截断、以及网络挂载/同步盘把对象写坏。损坏不等于没救——git 的内容寻址结构意味着只要同一内容在远端、克隆或备份里还存在一份,就能补回来。如果是磁盘满而不是真损坏,转 Git 磁盘写满速查。
本文要回答的问题
loose object <哈希> is corrupt里的那串哈希是什么,能修吗?- 如何用
git fsck把损坏范围一次摸清? - 坏掉的对象去哪找一份完好的补回来?
- 异常关机后整个仓库命令都 fatal,是先修对象还是先修索引?
- 没有远端、没有备份的单机仓库还能救回多少?
一、报错原文与典型现象
对象损坏的报错集中在读对象的路径上(远端仓库地址以 git.example.com 占位,路径以 /proj/demo 占位):
$ git status
error: object file .git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 is empty
fatal: loose object 4b825dc642cb6eb9a060e54bf8d69288fbee4904 (stored in .git/objects/4b/...) is corrupt$ git fsck --full
error: sha1 mismatch 4b825dc642cb6eb9a060e54bf8d69288fbee4904
error: inflate: data stream error (incorrect header check)
missing blob 4b825dc642cb6eb9a060e54bf8d69288fbee4904$ git log
fatal: bad object HEAD
# 或异常关机后的混合症状
fatal: index file corrupt读现象先分三档:单个 loose object 报 corrupt/empty/mismatch 是「点状损坏」,一个对象的事;fsck 扫出 missing blob/tree/commit 一串是「链状断裂」,某个对象引用的下一级丢了;fatal: bad object HEAD 加 index file corrupt 往往是异常关机后的「面状残局」,对象、索引、引用可能各坏一处。三档处置顺序不同:先摸清范围再动手。
二、病因处置速查表
| 报错现象 / 场景 | 可能原因 | 快速验证 | 处置 |
|---|---|---|---|
| loose object is corrupt/empty | 磁盘坏块或异常关机写一半 | git fsck --full 确认范围 | 删坏对象,从远端/克隆补回 |
| sha1 mismatch | 文件被外部程序改写或同步盘写坏 | 对比文件大小与修改时间 | 找完好副本替换,修不好就重克隆 |
| missing blob/tree/commit | 上游对象丢失,链路断裂 | fsck 报 missing 条目 | 从备份或远端 fetch 同哈希对象 |
| fatal: bad object HEAD | 引用文件损坏或 HEAD 指向丢失 | 直接 cat .git/HEAD 与 refs | 重建 refs,再修对象 |
| fatal: index file corrupt | 异常关机时索引写到一半 | git status 全 fatal | 删 .git/index,reset 重建 |
| 整库命令全挂、fsck 报一片 | 磁盘写满时提交或文件系统错误 | df -h 与 dmesg 看 I/O 错误 | 先救文件系统,再逐对象修复或换盘重克隆 |
三、排查决策图
下面这张图是标准排查路线,颜色按角色区分:红是报错入口与命中的根因,蓝是排查动作,绿是通过分支,橙是修复动作,紫是防复发沉淀。
读这张图抓分水岭:fsck --full 的输出规模决定路线——只报一两个对象 corrupt 走左支,删了补回即可;报一串 missing 加上 bad object HEAD/index file corrupt 走右支,要按「引用 → 索引 → 对象」的顺序重建,最后才补内容。两支殊途同归:补回的来源永远是远端、另一个克隆或备份,没有第二份完好的内容时救回能力有限。
四、逐条排查展开
先用 fsck 摸清范围,不要急着删文件。 git fsck --full --no-dangling 会完整扫一遍对象库:corrupt 是文件在但内容对不上;missing 是别的对象引用它但文件不在;dangling 是没被任何引用指到的孤儿(多数是历史残留,不算损坏)。把输出里 corrupt 和 missing 的哈希记下来,这就是要处理的清单。顺手看一下 df -h 和系统日志里有没有磁盘 I/O 错误——如果磁盘本身在报错,先换盘再修仓库,不然修完还会再坏。
点状损坏:删掉坏对象,从别处补同哈希的完好副本。 loose object 的路径就是哈希本身:.git/objects/4b/825dc...。修法是先把这个坏文件删掉(它已不可信),然后补回:有远端就 git fetch origin(对象在远端可达时 fetch 会顺带拉回来);有本机另一个克隆就把对应文件直接拷过来;对象在 pack 里也有一份的话,删掉 loose 文件后 git 会自动去读 pack 里的。补回后再跑一遍 git fsck --full,没有这条报错即修复成功。千万别试着「编辑」坏文件——对象内容是 zlib 压缩的二进制,手改只会错得更远。
链状断裂:missing 的对象按类型分级救。 missing blob 只影响一个文件的历史版本,如果工作区当前文件还在,重新 git add 提交就能重建内容(哈希相同的话对象复用);missing tree/commit 影响的是一个历史快照,能补则补、补不上就只能接受那段历史丢失。源头有远端时最省事:git fetch 把可达对象重新拉齐,缺的通常能补齐。
HEAD 与引用坏了:先重建引用再谈对象。 fatal: bad object HEAD 多半是 .git/HEAD 或 .git/refs/heads/<分支> 文件被写坏。直接 cat .git/HEAD 看它指向哪个分支,再 cat 那个 ref 文件:正常应是一行 40 位哈希。如果内容损坏,从 reflog 找分支最近的正确位置(cat .git/logs/refs/heads/<分支> 最后一行的第二个哈希),用 git update-ref refs/heads/<分支> <哈希> 重建。引用通了,git status 才可能跑起来。
索引损坏最简单:删掉重建。 fatal: index file corrupt 时直接 rm .git/index && git reset(默认 mixed reset,只重建索引不动工作区文件),之后 git status 重新暂存即可。索引只是暂存区的缓存,删了不丢任何已提交内容。
没有远端没有备份时的底线。 单机仓库的恢复上限取决于 reflog 和 dangling 对象还在不在:git fsck --lost-found 会把孤儿对象写到 .git/lost-found/ 下,commit 类孤儿可以用 git show <哈希> 看内容、git branch rescue <哈希> 救成分支。这也说明一条纪律:仓库要有远端,且要常 push。
修复顺序总纲:先保存现场再动手。 整个 .git 目录在动手修之前先 cp -r 留一份副本——修复动作本身(删对象、重建引用、跑 gc)都可能改变现场,副本是回头的路。有副本在手,修复做砸了可以推倒重来;没有副本,一次误删可能把唯一还能读的对象也清掉。副本占的磁盘空间相对丢代码的代价可以忽略,这一步不要省。
多人协作仓库的额外一步。 仓库是多人共用的(比如共享目录或镜像仓),修好之前要先通知其他人暂停 push——你重建引用、补对象的过程中,别人推上来的新对象可能和你的修复动作交错,把现场搅得更乱。修复完成、fsck 全绿后,再让大家正常推送。单克隆出问题就简单得多:最快路线往往是「备份工作区未提交改动 → 重新克隆 → 把改动挪回去」,十分钟完工,比在坏库里逐对象修复划算得多。
五、规范做法与预防
- 远端常推:
git push是最便宜的对象备份,任何「只有一个副本」的对象都是单点。 - 关机与杀进程纪律:正在跑 git 命令时不要强杀、不要断电;笔记本合盖前先让长命令跑完。
- 磁盘健康巡检:出现一次对象损坏就要查磁盘 SMART/文件系统,坏块不会只坏一次。
.git目录不进同步盘/清理清单:网盘同步.git、清理脚本rm大文件,是对象损坏的两大人为来源。- 定期
git fsck:重要仓库挂在 cron 里每周跑一次,损坏早发现早补(远端还有时补得回)。 - 打包收紧:
git gc把 loose object 收进 pack 并带校验,长期仓库定期跑能减少散文件损坏面。
这一篇在知识体系里的位置
本篇是 Git 排错速查簇的仓库完整性入口篇:磁盘写满导致的提交失败看 Git 磁盘写满速查;索引锁残留导致的命令被拒看 Git index.lock 速查;误删提交想找回的看 Git stash 找回速查 与 tag、reflog 与 bisect。「先 fsck 定范围、再按引用/索引/对象分层重建、内容从第二副本补」这条主线对一切仓库损坏通用。
一句话总结
Git 对象损坏先跑 git fsck --full 摸清范围:单个 loose object corrupt 是点状损坏,删掉坏文件后从远端 fetch、另一个克隆或 pack 里补回同哈希完好副本;missing 一串或 HEAD/index 也坏是面状残局,按「重建引用 → 重建索引 → 补对象」的顺序分层修。内容寻址结构决定了恢复上限是「别处还有没有同一份内容」,所以根上的预防只有一条:远端常 push、.git 不进同步盘、磁盘坏了先换盘再修仓库。