Appearance
打包与垃圾回收
Git 会随着使用积累大量对象文件。打包和垃圾回收机制帮助优化存储效率,保持仓库健康。
git gc 垃圾回收
git gc(Garbage Collect)是 Git 的维护命令,执行多个优化操作:
bash
# 执行垃圾回收
git gc
# 更激进的清理
git gc --aggressive
# 安静模式(不显示进度)
git gc -q
# 立即清理(不等待过期时间)
git gc --prune=nowgit gc 执行的操作:
- 压缩松散对象为打包对象(pack files)
- 清理不可达的对象(超过保留期限的)
- 清理过期的 reflog 记录
- 打包引用(pack-refs)
- 清理临时文件
Git 也会自动触发 gc:
- 当松散对象超过 6700 个(
gc.auto配置) - 当 pack 文件超过 50 个(
gc.autoPackLimit) - 执行
git push时(在远程端)
git prune 清理不可达对象
git prune 清理不可达的对象(没有任何引用指向的对象):
bash
# 清理不可达对象(默认保留 2 周内的对象)
git prune
# 立即清理所有不可达对象(谨慎!)
git prune --expire=now
# 预览哪些对象会被清理(不实际执行)
git prune -n
git prune --dry-run
# 详细输出
git prune -v什么是不可达对象:
- 被 reset 丢弃的提交(reflog 过期后)
- 被 rebase 重写的旧提交
- 被 amend 替换的旧提交
- 未完成的合并产生的临时对象
打包文件(.pack / .idx)
Pack 文件结构
.git/objects/pack/
├── pack-abc123.idx ← 索引文件:存储 SHA-1 到 pack 内偏移量的映射
└── pack-abc123.pack ← 数据文件:所有对象的压缩数据Pack 文件的优化原理:
松散对象(低效):
Commit A: 完整快照(5MB)
Commit B: 完整快照(5.1MB) ← 只比 A 多 0.1MB,但存了 5.1MB
Pack 文件(高效):
Commit B: 完整快照(5.1MB)
Commit A: delta(B 与 A 的差异)(0.1MB) ← 大量节省空间Git 选择相似度高的对象作为 delta 基准,而不一定是"较新版本存 delta"。实际上,通常存储最近版本的完整对象,旧版本存差异(因为最新版本最频繁访问)。
手动操作 Pack 文件
bash
# 手动创建 pack 文件
git pack-objects .git/objects/pack/pack << 'EOF'
abc123
def456
ghi789
EOF
# 对所有对象重新打包(激进优化)
git repack -a -d -f --depth=250 --window=250
# -a:将所有对象打包(包括已有 pack 中的)
# -d:删除旧的 pack 文件
# -f:强制重打包
# --depth:delta 链的最大深度
# --window:计算 delta 时比较的窗口大小git verify-pack 查看打包内容
bash
# 查看 pack 文件中的对象列表
git verify-pack -v .git/objects/pack/pack-abc123.idx
# 输出格式:
# SHA-1 类型 大小 压缩大小 [偏移量 [delta基准SHA-1]]
# abc123 commit 423 290 12
# def456 blob 102400 1024 302 ghi789 ← delta 对象
# 按大小排序,找出最大的对象
git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -20git count-objects 统计对象
bash
# 简单统计
git count-objects
# 42 objects, 1024 kilobytes
# 详细统计
git count-objects -v
# count: 42
# size: 1024
# in-pack: 1500
# packs: 3
# size-pack: 2048
# prune-packable: 0
# garbage: 0
# size-garbage: 0
# 以 MB 为单位显示
git count-objects -v -Hgit maintenance 自动维护(Git 2.31+)
新版 Git 提供了更现代的维护机制:
bash
# 启动后台自动维护
git maintenance start
# 停止自动维护
git maintenance stop
# 手动运行维护(所有任务)
git maintenance run --auto
# 运行特定任务
git maintenance run --task=gc
git maintenance run --task=commit-graph
git maintenance run --task=prefetch
git maintenance run --task=loose-objects
git maintenance run --task=incremental-repack自动维护的任务:
loose-objects:将松散对象打包incremental-repack:增量重打包commit-graph:更新提交图(加速git log等操作)prefetch:后台预获取远程更新gc:完整的垃圾回收
仓库健康检查
bash
# 检查对象完整性
git fsck
# 详细检查
git fsck --full --strict
# 输出示例(有问题时):
# error: object file .git/objects/ab/cd... is empty
# error: sha1 mismatch ab...
# dangling blob abc123 ← 不可达但未过期的对象
# dangling commit def456常见问题处理:
bash
# 修复损坏的对象(通常需要从备份或远程恢复)
git fsck --full
git fetch --all
git gc --prune=now
# 完整恢复流程
git remote -v
git fetch origin
# 从远程重新克隆(极端情况)
cd ..
git clone <url> repo-recovered总结
| 操作 | 命令 | 效果 |
|---|---|---|
| 垃圾回收 | git gc | 打包、清理、优化 |
| 清理不可达对象 | git prune | 删除孤立对象 |
| 查看 pack 内容 | git verify-pack -v | 分析 pack 文件 |
| 统计对象 | git count-objects -v | 查看存储使用 |
| 启动自动维护 | git maintenance start | 后台定期维护 |
| 仓库健康检查 | git fsck | 验证数据完整性 |
定期执行 git gc 或启用自动维护,可以保持仓库高效运行,特别是对于历史悠久、活跃度高的大型仓库。