赞
踩
Git官方文档:Git - Reference (git-scm.com)
Git原理部分,这篇我觉得写得挺好的:http://teohm.com/blog/learning-git-internals-by-example/
参考文档:
https://git-scm.com/docs/git-filter-branch
git filter-branch是一个可以用来清洗整个历史记录的工具。
下面我们通过Git仓库大文件清理来介绍下命令:
git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5 | awk '{print $1}')"
找出占空间最大的前5个数据对象对应的文件。
git gc
git 会定期运行git gc命令,收集所有松散对象并将它们放到包文件中,将多个包文件合并为一个大的包文件,移除与任何提交都不相关的陈旧对象。就是把objects下面的文件压缩到packed-refs下。
Git往磁盘保存对象时默认使用的格式叫松散对象(loose object)格式(放在.git/objects文件夹下)。Git时不时地将这些对象打包至一个叫packfile的二进制文件(放在.git/objects/pack文件夹中)以节省空间并提高效率。当仓库中有太多的松散对象,或是手工调用git gc命令,或推送至远程服务器时,Git都会这样做。
松散对象一般是由本地的git add, git commit产生的。
关于Git对象可以查看官方文档的内部原理部分。
为了获得指定引用的正确 SHA-1 值,Git 会首先在 refs
目录中查找指定的引用,然后再到 packed-refs
文件中查找。 所以,如果你在 refs
目录中找不到一个引用,那么它或许在 packed-refs
文件中。
git verify-pack
如何找出哪个文件或哪些文件占用了空间?如果你执行git gc 命令,所有对象将被放入一个包文件中,你可以通过运行git verify-pack命令,对输出内容的第三列(即文件大小)进行排序,从而找出大文件。
$ git verify-pack -v .git/objects/pack/pack-29…69.idx \
| sort -k 3 -n \
| tail -3
dadf7258d699da2c8d89b09ef6670edb7d5f91b4 commit 229 159 12
033b4468fa6b2a9547a70d88d1bbe8bf3f9ed0d5 blob 22044 5792 4977696
82c99a3e86bb1267b236a4b6eff7868d97489af1 blob 4975916 4976258 1438
git rev-list
为了找出大对象具体是哪个文件,可以使用rev-list命令。git rev-list是Git底层命令,你可以获取所有提交的SHA-1值列表。git rev-list类似git log,但它默认只输出SHA-1值。如果你传递 --objects
参数给 rev-list
命令,它就会列出所有提交的 SHA-1、数据对象的 SHA-1 和与它们相关联的文件路径。
$ git rev-list --objects --all | grep 82c99a3
82c99a3e86bb1267b236a4b6eff7868d97489af1 git.tgz
git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch "bigfile"' \
--prune-empty --tag-name-filter cat -- --all
这里–force是为了防止有另外的一个filter-branch正在运行,所以–force会强行终止别的filter-branch。如果要删除的是文件夹,则要在‘git rm --cached’命令后面加上-r,表示递归。
*git filter-branch --index-filter*
让每个提交的文件都复制到索引(.git/index)中
然后运行过滤器命令:*git rm --cached --ignore-unmatch 文件名 ,*让每个提交都删除掉“文件名”文件
然后--prune-empty 把空的提交“修剪”掉
然后*–tag-name-filter cat* 把每个tag保持原名字,指向修改后的对应提交
最后-- --all 将所有ref(包括branch、tag)都执行上面的重写
这些缓存对象给你提供了撤销操作的一次机会
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
上面2步把大文件的索引都切断了,这个时候进行垃圾回收,就可以很明显看到效果了。回收空间,清理本地仓库不可达对象。
–aggressive会更加多的优化仓库,但也更加消耗时间。
–prune= 修剪比指定时间更老的松散对象。
git gc --aggressive --prune=now
可以看到直接运行git gc, 只是把松散对象压缩到pack中。但是git gc --prune会将不可达的松散对象从仓库中移除掉。
这时候普通的push是不行的,需要强制推送。
git push --force
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。