git 项目体积过大 (object文件夹)
step01
git gc
清理不必要的文件并优化本地存储库
step02
首先了解一下.git文件下的文件含义
$ ls
HEAD #指向当前分支
branches/ # 目录
config # 项目特有的配置选项
description # 仅供 GitWeb 程序使用
hooks/ # 保存了客户端或服务端钩子脚本
index # 保存了暂存区域信息
info/ # 保存了一份不希望在 .gitignore 文件中管理的忽略模式 (ignored patterns) 的全局可执行文件
objects/ # 存储所有数据内容
refs/ # 存储指向数据 (分支) 的提交对象的指针
git add
和git commit
的过程中,保存修改了的文件的blob
,更新索引,创建tree
对象,最后创建commit
对象,这些commit
对象指向了顶层tree
对象以及先前的commit
对象。这三类 Git 对象 ──blob
,tree
以及commit
── 都各自以文件的方式保存在.git/objects
目录下。所以,当你提交了一个体积特别大的文件后,会记录在
objects
文件夹下,删除一个文件,只是记录了删除这个操作,但并不会把文件从.git
文件夹删除。 当你直接从项目中删除该文件,.git
文件夹完全不会变小(理论上还会变大一点,因为多记录了一次删除操作。。。)
找到大文件
git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5 | awk '{print$1}')"
#命令解析:
#rev-list 命令用来列出Git仓库中的提交,我们用它来列出所有提交中涉及的文件名及其ID。 该命令可以指定只显示某个引用(或分支)的上下游的提交。
#–objects:列出该提交涉及的所有文件ID。
#–all:所有分支的提交,相当于指定了位于 /refs 下的所有引用。
#verify-pack 命令用于显示已打包的内容,我们用它来找到那些大文件。
#-v(verbose)参数是打印详细信息。
删除大文件
git filter-branch --force --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch YOUR-FILE-NAME' --tag-name-filter cat -- --all
#命令解析:
#filter-branch命令可以用来重写Git仓库中的提交
#–index-filter参数用来指定一条Bash命令,然后Git会检出(checkout)所有的提交, 执行该命令,然后重新提交。
#–all参数表示我们需要重写所有分支(或引用)。
#YOUR-FILE-NAME 你查找出来的大文件名字
如果直接删除整个文件夹
$ git filter-branch --force --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch 文件夹名称' --tag-name-filter cat -- --all
回收
虽然上面我们已经删除了文件, 但是 repo
里面仍然保留了这些 objects
, 等待垃圾回收(GC), 所以要用命令彻底清除它, 并收回空间,命令如下:
rm -rf .git/refs/original/
git reflog expire --expire=now --all
git gc --prune=now
注:这里面最重要的两条命令是
git filter-branch
和git gc
,filter-branch
真正在清理,但是只运行它也是没用的,需要再删除备份的文件,重新打包之类的,最后的gc
命令,用来收集产生的垃圾,最终清除大文件。
完成后,以强制覆盖的方式推送你的 rep
, 命令如下:
git push --force --all
git remote -v
git remote remove origin
git remote add origin https://
git push -u origin --all
如果这个问题是你在push的时候发现的肯定会报错
如下解决:
Cannot rebase: You have unstaged changes.
说明有修改过的文件
git stash
git pull --rebase (每次push之前最好这样做一次)
git push …
之后用git stash pop stash