处理git下的objects越来越大的问题

  |  

摘要: 本文介绍在 git 项目中随着提交越来越多,objects 越来越大的解决办法。

【对数据分析、人工智能、金融科技、风控服务感兴趣的同学,欢迎关注我哈,阅读更多原创文章】
我的网站:潮汐朝夕的生活实验室
我的公众号:潮汐朝夕
我的知乎:潮汐朝夕
我的github:FennelDumplings
我的leetcode:FennelDumplings


问题

.git/objects/pack 文件过大,可能是由于开发过程中上传过大文件,后来删除了,但是仍然保存在 git 记录中。

有两个解决办法:

  1. 删除远程仓库上的项目,重新提交
  2. 彻底清除历史记录

第 1 个办法比较简单,并且实测有效,本文我们看第 2 个办法。

.git 文件结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
├── COMMIT_EDITMSG
├── HEAD
├── FETCH_HEAD
├── ORIG_HEAD
├── config
├── description
├── index
├── packed-refs
├── branches/
├── hooks/
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── prepare-commit-msg.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ └── update.sample
├── info/
│ ├── exclude
│ └── refs
├── logs/
│ ├── HEAD
│ └── refs/
│ ├── heads/
│ │ └── master
│ └── remotes/
│ └── origin/
│ ├── HEAD
│ └── master
├── objects
│ ├── 00
│ │ ├── 092b232b4ca2f5bafc369fa6f16ee257ebc0f8
│ │ └── ...
│ ├── 02
│ │ ├── d3a06046cf6d313a12ecc29d3cc4e68c5d9cc5
│ │ └── ...
│ ├── ...
│ ├── info/
│ │ └── packs
│ └── pack/
│ ├── pack-*.idx
│ └── pack-*.pack
└── refs
├── heads/
│ └── master
├── remotes/
│ └── origin/
│ ├── HEAD
│ └── master
└── tags/

其中一些文件或目录的含义如下:

  • description: 用于 GitWeb 程序
  • config: 配置特定于该仓库的设置
  • hooks: 放置客户端或服务端的 hook 脚本
  • HEAD: 指明当前处于哪个分支
  • objects: Git 对象存储目录
  • refs: Git 引用存储目录
  • branches: 放置分支引用的目录

每次 git add 会生成一个 git 对象,称为 blob 对象,存在 objects 目录下。

这个 blob 对象保存的内容如下:

git add 时,会把文件文正保存为一个新的 blob 对象。通过 git gc 打包,或者每次 git push 的时候 git 会自动执行一次打包,将 blob 对象合并成一个包文件,同时生成一个索引文件,索引文件中包含了每个 blob 对象在包文件中的便宜信息,git 在打包的过程中使用了增量编码,之保存 blob 对象的不同版本间的差异。

git 会对 Blob 对象进行合并优化,因此 objects 文件夹正常来讲不会那么大。但是频繁更换文件时,objects 下的 pack 文件会越来越大。虽然被替换或被删除的文件后续可能用不到删除了,但是 pack 中的缓存还是会一直存在。

清除历史记录的流程

识别出最大的五个文件

1
git verify-pack -v .git/objects/pack/pack-*.idx | sort -k 3 -g | tail -5

结果:

1
2
3
4
5
a5feec3a1471d1df393ff4716a403cf1c0b58e6d blob   63546688 50472218 748940873
6ef2825ab425a3cf0e22023c02a49036a8532d0a blob 64807763 63630746 1392991986
b5bc644edbcbaa32a8322714ef0ac99e2f48de97 blob 65269414 63722713 307534912
bed09687996f08223a364e7bfe480404740596df blob 84343272 84273880 1268892618
418740151dffba70c727f4ffea1f069927f40301 blob 84745953 80225046 1498620076

查看所有提交记录

1
git rev-list --all

由对象 ID 查询到原始的大文件:

1
git rev-list --objects --all | grep 418740151dffba70c727f4ffea1f069927f40301

结果:

1
source/download/pdf/book/线性代数的几何意义.pdf

filter-branch 将文件从历史记录的所有 tree 中删除

1
git filter-branch --index-filter 'git rm --cached --ignore-unmatch source/download/pdf/book/线性代数的几何意义.pdf

然后执行以下命令:

1
2
3
4
5
6
7
8
9
rm -rf .git/refs/original/

git reflog expire --expire=now --all

git fsck --full --unreachable

git repack -A -d

git gc --aggressive --prune=now

删除完成后,提交

1
git push --force --all

Share