如何清理 Git 仓库
仓库原来越大的原因
git
会把文件的每一个差异化版本都记录在案。即使你只改动了某个文件的一行内容,git
也会生成一个全新的 blob
对象来存储新的文件内容。git gc
打包或者每次 git push
的时候 git
都会自动执行一次打包过程,将 blob
对象合并成一个包文件,同时会生成一个索引文件,索引文件中包含了每个 blob
对象在包文件中的偏移信息,在打包的过程中使用了增量编码方案,只保存 blob
对象的不同版本之间的差异,这会减缓仓库变大的速度。但是整体还是一个上涨的过程。
处理方法
方法一
方法一的核心是清理大文件或者不再需要的文件 (后文统称为冗余文件),以及他们所产生的提交记录。下面的操作一定要三思而行,真的会把文件删除的哟!
找到所有冗余文件的 git 记录
shellgit rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5 | awk '{print $1}')"
解释一下上面的代码:1. 倒序列出的提交引用的任何对象的对象 id 2. 读取 git 归档后的 idx 文件,列出所有的对象列表,然后根据列表中的第三项 (size) 进行升序排序,然后取最后 5 项,截取第一列(SHA-1)3. 取操作一和操作二的交集,便是当前仓库中占用空间最大的 5 个文件或提交记录
删除冗余文件以及相关提交记录
删除时,一定要核对好,因为上面一步输出的既包含了提交记录中的大文件,也包含当前仓库中的大文件。
删除文件
shellgit filter-branch --force --index-filter \ 'git rm --cached --ignore-unmatch 文件名' \ --prune-empty -- --all
删除文件夹
shellgit filter-branch --force --index-filter \ 'git rm -r --cached --ignore-unmatch 文件夹名' \ --prune-empty -- --all
删除缓存对象
shellgit for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin git reflog expire --expire=now --all git gc --prune=now
推送至远程仓库
当你确认你的操作都没有问题后,就可以强制推送到远程了。
shellgit push --force
方法二
方法二比较暴力,直接将整个仓库的历史全部删掉,以达到对 git 仓库瘦身的目的。
删除所有的远程分支
shellgit branch -r | grep origin | grep -v '>' | grep -v master | xargs -L1 | awk '{sub(/origin\//,"");print}'| xargs git push origin --delete
删除本地的.git 文件夹
shellrm -rf .git
初始化本地的 git 仓库
shellgit init git add . git commit -m "init"
将本地的 git 仓库与已有的远程仓库进行关联
shellgit remote add origin 远程仓库地址 (https://xxx.git 或 git@xxx.git 均可)
强制推送到远程仓库
shellgit push -f origin master