对象库损坏并不罕见:磁盘错误、不完整复制、手工改
.git/objects、云同步工具冲突。git fsck
遍历对象与引用,报告
corrupt、dangling、missing
等类型。分清「真损坏」与「悬空未引用」,决定能否从备份或
reflog 恢复。
一、fsck 查什么
git fsck(全称 filesystem
check)主要验证:
- 松散/pack 对象 zlib 可解压、哈希与 ID 一致。
- tree 条目指向存在的对象;commit parent 存在。
- tag 指向合法对象。
- ref 文件 SHA 存在对应对象。
- 图谱无断裂(配置深度时)。
不加参数时报告悬空对象(dangling)为
informational;--full 更彻底。
二、corrupt loose object 实测
对含松散对象的仓库,取一对象文件,先
chmod u+w(松散对象默认只读),截断最后一字节:
OBJ=.git/objects/83/096816d05d4fe8d052a9726dc217daed3d2091
chmod u+w "$OBJ"
truncate -s -1 "$OBJ"
git fsck输出(Git 2.54.0):
error: corrupt loose object '83096816d05d4fe8d052a9726dc217daed3d2091'
fatal: loose object 83096816d05d4fe8d052a9726dc217daed3d2091 (stored in .git/objects/83/096816…) is corrupt
说明 zlib 或长度校验失败。修复:从备份还原该对象文件,或
git fetch 从远端重新拉取缺失对象。
三、常见报告类型
| 类型 | 含义 | 典型处理 |
|---|---|---|
corrupt loose object |
文件内容坏 | 还原对象或 re-fetch |
bad sha1 file |
ref 文件非合法 SHA | 手工或从备份修 ref |
dangling commit/blob/tree |
无 ref 可达但仍存在 | 通常可忽略;或 git gc prune |
missing blob/tree/commit |
引用指向不存在的对象 | 严重;需从远端/备份补对象 |
error in pack |
pack 校验失败 | 删除坏 pack 并 re-fetch |
四、dangling 与丢失的区别
dangling:对象完好,只是没有分支/tag
指向(例如 amend 后的旧 commit)。git fsck 列出
SHA;可用 git show <sha> 查看,或通过
reflog 找回。
missing:应有对象却不在库中——例如
partial clone 失败、手动删了 objects/
子目录。必须重新获取。
五、lost-found
git fsck --lost-found 把悬空
commit/tree/blob 挂到 refs/bisect/ 或
.git/lost-found/
下,便于人工检查。不是自动恢复分支。
六、pack 损坏
pack 尾部 SHA 覆盖整个 pack;单比特损坏可能导致整个 pack
不可用。处理:删除该 pack 与 idx,从 remote 重新 fetch(或
restore 备份)。git verify-pack -v
可提前扫描。
七、本文边界
- 不提供生产事故 runbook 全文。
- 不讨论
git replace等高级修补。
参考资料
- Git documentation,
git-fsckmanual page - 实验环境:Git 2.54.0(损坏实验在临时仓库执行)
系列索引:Git 内部结构 · 上篇:gc/repack · 下篇:porcelain 文件副作用
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【Git 内部】Git 内部结构:对象库与磁盘文件格式
从 .git 目录布局、松散对象与 packfile 格式,到 refs、index、reflog、gc/fsck 与 fetch/push 落地——用官方 format 文档与本地实测 dump 系统讲清 Git 把版本历史存在哪、每个命令改写了哪些文件。全 16 篇。
【Git 内部】.git 目录全景:三棵树与仓库布局
git init 之后 .git 里每个路径干什么?对照 gitrepository-layout 与本地 find 清单,建立 bare/non-bare、三棵树、objects/refs/index 的磁盘级地图。
【Git 内部】松散对象:zlib 载荷与 SHA-1 路径
blob/tree/commit 在磁盘上如何编码?对象头 type size、zlib 压缩、objects/ab/cdef 路径命名,对照 git hash-object 与手工 SHA-1 验证。
【Git 内部】对象图:tree、commit、tag 的链式结构
一次提交在对象库里如何连成链?tree 条目 mode/name/hash、commit 的 tree/parent 字段、annotated tag,用 git cat-file -p 展开并画对象图。