git仓库整理实战

来源:互联网 发布:mac chili色号 编辑:程序博客网 时间:2024/05/22 19:04

你的硬盘空间被谁偷走了?

我们经常被问到:你们项目代码量有多大?这时候你可能会去机器上执行:

$ du -sh 项目名

来看一下你的项目文件夹占用了多大的空间,然后自豪的指着结果说:看!我们一个月写了五百兆!

但是,这是真的吗?你了解500m的代码有多少吗?

今天我们从一个空仓开始,研究一下你这‘500m’是怎么来的。

首先,我们创建一个带workspace的空仓,然后看一下大小:

$ git init gc_test;$ cd gc_test$ du -sh ./100K    ./

只是100k,空仓嘛,可以接受。
向workspace中添加两个大文件呢?

$ cp ~/redis-2.8.3.tar.gz ./$ cp ~/workspace.tar.gz ./$ lltotal 15452drwxrwxr-x  3 git git     4096  729 11:07 ./drwxrwxr-x 12 git git     4096  729 10:51 ../drwxrwxr-x  7 git git     4096  729 10:51 .git/-rw-rw-r--  1 git git  1046106  729 11:07 redis-2.8.3.tar.gz-rw-rw-r--  1 git git 14761335  729 11:07 workspace.tar.gz

在add之前,我们看一下.git的大小:

$ du -sh ./.git/96K ./.git/

加入版本管理:

$ git add ./*$ du -sh ./31M ./$ du -sh ./.git/16M ./.git/

当你add之后,我们发现,仓库占的空间增加了一倍

接下来提交

$ git commit -m 'first commit'[master(根提交) 71ea434] first commit 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 redis-2.8.3.tar.gz create mode 100644 workspace.tar.gz$ du -sh ./31M ./$ du -sh ./.git/16M ./.git/

如何将空间释放回来

是不是删除了以后空间就会被完全释放呢?

$ git rm redis-2.8.3.tar.gz workspace.tar.gzrm 'redis-2.8.3.tar.gz'rm 'workspace.tar.gz'$ du -sh ./16M ./$ du -sh ./.git/16M ./.git/$ git commit -m 'remove redis and workspace'[master 9dd3d25] remove redis and workspace 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 redis-2.8.3.tar.gz delete mode 100644 workspace.tar.gz$ du -sh ./16M ./$ du -sh ./.git/16M ./.git/

哈哈,然而并没有!
现在我们也可以执行一个git命令来查看他的空间占用的详情

$ git ls-tree -l -r HEAD ./

我们看到仓库是workspace中啥也没有,那就是.git本身占了 16MB!

执行下面的命令,查找历史提交中删除了哪些文件,从中我们可以找到大文件的线索。即我们可以看到历史提交中删除了哪些大文件,这些大文件仍然保存在历史中。

$ git log --pretty="==== COMMIT %h ====" --stat --diff-filter=D --all==== COMMIT 9dd3d25 ==== redis-2.8.3.tar.gz | Bin 1046106 -> 0 bytes  workspace.tar.gz   | Bin 14761335 -> 0 bytes   2 files changed, 0 insertions(+), 0 deletions(-)

执行下面命令获取要删除的文件列表,并在每一行的前面自动添加 git 删除命令。

$ git log --pretty="==== COMMIT %h ===="   --stat --diff-filter=D --name-only --all |  sort -u | grep -v "^==== COMMIT" | grep -v "^$" |   sed -e 's/^\(.*\)$/git rm -r --cached --ignore-unmatch "\1"/g'  > /tmp/remove-trash-files.sh$ cat /tmp/remove-trash-files.shgit rm -r --cached --ignore-unmatch "redis-2.8.3.tar.gz"git rm -r --cached --ignore-unmatch "workspace.tar.gz"

执行下面的命令对仓库的所有分支和所有 tags 执行过滤。从输出中我们可以看出部分提交中发现了垃圾数据,执行了清理动作。

$ git filter-branch --index-filter 'sh /tmp/remove-trash-files.sh' --tag-name-filter cat -f -- --allRewrite 9dd3d252adc1a640796c1a3811d255569712f3b7 (2/2)WARNING: Ref 'refs/heads/develop' is unchangedWARNING: Ref 'refs/heads/master' is unchanged

现在仓库是不是变小了呢?我们来看一下:

$ du -sh ./16M ./

嗯?咋回事儿,为什么仓库没有变化呢,是不是我们上面哪儿有问题?
这其实是由于git对历史数据的保护造成的,在本地仍然有一些关联引用和reflog,在关联着这些数据,如果不删了这些关联数据和log,空间是不会被释放的。
1、删除ref中的备份引用:

$ git show-ref | awk '{print $2}' | grep refs/original/ | xargs -I{} git update-ref -d {}

2、清空reflog:

$ git reflog expire --expire=now --all

最后,还要执行gc进行垃圾回收,将所有松散对象都清除,否则这些松散对象仍然会被保留一段时间(gc好像是定期清除的,具体多长时间,怎么设置,可以通过帮助文档了解到)

$ git gc --prune=now --aggressive

现在我们来看一下仓库变成多大了:

$ du -sh ./140K    ./

这个方法适合bare仓吗?应该是适合的,不过我没试~

1 0