前言
最近在做人脸识别的项目,接手了一个代码,发现git clone很慢,一看发现.git很大,主要原因是模型文件也存储在git上,这怎么能行呢?果断做了两件事,第一,模型管理不在git,移到云盘,使用脚本下载,第二,减小.git大小(.git达6-7GB)。
那么首先讲一下,为什么.git会变得很大呢???Git 作为一个分布式的版本管理工具,代码仓库中是会保存所有历史记录的。虽然,Git 的 .gitignore 文件里可以定义一些忽略文件的规则,但是,在我们提交代码的过程中,总会不小心误提一些没用的文件,如果文件中存在大文件,就会导致:就算我们把它删了重新提交,.git 文件夹依然会占用较大的空间。
如何解决这个问题呢?其实,Git 已经为我们提供了解决方案,就是被称为核弹级的命令 filter-branch。这个命令可以用来修改历史提交记录,把不需要的文件永久地从历史记录中删除。
方法如下:
首先,我们需要找出大文件。
找出排名前 10 的 pack 记录,命令如下:
git verify-pack -v .git/objects/pack/pack-*.idx | sort -k 3 -g | tail -10
看到如下信息:
b4f24922704061dd41791c3fa138535bdd64047c blob 12159456 10562199 116259793
27017d5df3c9b05786568b1f85863f9f008a464f blob 12160016 10558102 138991863
7009fc1de527e8670e59cf291c659d2541b55188 blob 12707936 11223144 412145772
1cf58693e816034bd210edd0c73a3ab158a8f27a blob 13535824 1480718 90483581
8406e9a6b0dd22381e6bdc1312b293ba60084fd6 blob 13703424 12169871 126821992
e0f54b006ee5fc3ead71d503c7014ed407d08d4f blob 13878960 12302651 423368916
1d168908ee7a0c1fa158038e9134a1155f0e35e0 blob 13964768 10103585 377394839
3cb667151ef9338aacda90e3d66eb916b8a1128a blob 14946592 1608505 88867011
3a8e3688bd4d355174f70915cadbc3ebe4393f7c blob 14990160 12956157 388455577
70c27b00ecf865a97a5b107403d1fc36f5154266 blob 16177592 3269692 74912525
最后一条就是最大的一条记录,70c27b00ecf865a97a5b107403d1fc36f5154266是它的 id。
找出该记录对应的文件:
git rev-list --objects --all | grep 70c27b00ecf865a97a5b107403d1fc36f5154266
可以看到如下文件信息:
2ec0deab6d9e97802ace6874634ecfa9de944bc5 data/nnie_model/vehicle/person_bike_car.wk
这个文件是模型文件,而且还有其他更多的模型文件,都可以移除。
将该文件从历史记录中移除:
git log --pretty=oneline --branches -- data/nnie_model/vehicle/person_bike_car.wk
或者通过对整个文件夹移除,vehicle/下的所有文件会被移除
git log --pretty=oneline --branches -- data/nnie_model/vehicle/*
重写所有 commit,将该文件从 Git 历史中完全移除:
git filter-branch --index-filter 'git rm --cached --ignore-unmatch data/nnie_model/vehicle/person_bike_car.wk -- --all
移除整个文件
git filter-branch --index-filter 'git rm --cached --ignore-unmatch data/nnie_model/vehicle/*' -- --all
到这里,历史记录中已经没有该文件了。不过运行 filter-branch 产生的日志还是会对该文件有引用,所以还需要运行以下几条命令,把该文件的引用完全删除:
rm -Rf .git/refs/original
rm -Rf .git/logs/
git gc
git prune
这个时候,再看文件夹,已经小了很多了。然后就可以 push 代码了,不过就是需要强制 push:
git push --force
通过下面的命令可以看一下.git文件的确小了很多。
du -h --max-depth=1
以上就是删除 Git 历史记录中大文件的过程。
上面的方式亲测好用,网上还有其他的方式,但是我用起来不生效。
git filter-branch --index-filter 'git rm --cached --ignore-unmatch '
rm -rf .git/refs/original/
git reflog expire --expire=now --all
git fsck --full --unreachable
git repack -A -d
git gc --aggressive --prune=now
git push --force [remote] master
最后一步会出错,替换成git push --force提示无更新内容。