Git文件夹太大,BGFBlob历史可行吗?

摘要:我们使用Git来管理项目的时候,可能会提交一些Blob的二进制文件,这些文件并不能像文本文件一样采用diff delta的形式进行版本控制。如果这些文件一直跟随master的主版本,那么就是属于有效的文件。 然而很多时候这些二进制文件会被删
我们使用Git来管理项目的时候,可能会提交一些Blob的二进制文件,这些文件并不能像文本文件一样采用diff delta的形式进行版本控制。如果这些文件一直跟随master的主版本,那么就是属于有效的文件。 然而很多时候这些二进制文件会被删除重建,那么由于Git的特性,这些文件会一直留在Git的历史记录中,这样会导致Git仓库变得庞大,不利于版本控制和迁移。最直观的就是clone的时候会很慢,而使用--depth=1则无法看到历史提交的代码。 查找历史文件 历史提交的二进制文件通常我们可以认为是不需要的,然而在多人协作的时候这个事情我们并不能非常确定。因此我们需要主动查找较大的二进制文件来处理,最简单的办法就是直接扫描大文件。 git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -10 | awk '{print$1}')" 通过这个命令我们可以看到历史提交中最大的10个文件,然后我们可以根据这个文件的hash值来查找这个文件的提交记录。如果需要看到文件的大小,也可以再补充下输出。 git verify-pack -v .git/objects/pack/*.idx \ | grep blob \ | sort -k 3 -n \ | tail -10 \ | awk '{print $1, $3}' \ | while read -r hash size; do file=$(git rev-list --objects --all | grep "$hash") echo "$file $size" done BFG Repo-Cleaner 虽然可以使用git-filter-branch来处理历史提交,但是这个命令的效率比较低,且容易出现错误。BFG是一种更简单、更快捷的替代方法,主要是用来处理历史提交的文件,可以删除指定的文件,也可以替换文件内容。 BFG需要使用Java来运行,因此需要先确保运行环境JDK >= 8。之后使用git clone --mirror来克隆仓库,然后使用BFG来处理历史提交。 git clone --mirror git://example.com/some-big-repo.git 需要注意的是,使用--mirror标识会将整个仓库的完整副本克隆下来,包括所有的提交历史,并且不会存在任何普通文件。同样的,当处理完成之后这个仓库所有的分支都会被修改,因此需要谨慎操作。 而如果仅处理单个分支,那就是使用常规的git clone即可。但是需要注意的是,由于其他分支仍然有可能持有旧的分支内容,因此就必须要将所有涉及到的分支依次处理,这样就非常麻烦了。 接下来就是使用BFG来处理历史提交,BFG的使用非常简单,只需要指定需要处理的文件即可。下载BFG的jar包可以在https://rtyley.github.io/bfg-repo-cleaner/中找到。 java -jar bfg.jar --delete-files path/to/file.txt some-big-repo.git BFG还提供了一些其他的功能,比如删除指定大小的文件、替换文件内容、删除文件夹、删除文件通用匹配符。 java -jar bfg.jar --strip-blobs-bigger-than 1M some-big-repo.git java -jar bfg.jar --replace-text pwd.txt some-big-repo.git java -jar bfg.jar --delete-folders path some-big-repo.git java -jar bfg.jar --delete-files '*.png' some-big-repo.git 但是这里的匹配模式也存在局限,例如无法同时指定文件和大小,例如需要移除> 1M的png文件是做不到的,经过测试其匹配模式总是倾向于后设置的模式。不过这里并没有阅读源码,只是简单的测试判断。 此外,不需要担心BFG会删除HEAD的提交,BFG不会处理HEAD的提交,即使BFG会从早期的历史记录中删除文件,当然也可以通过--no-blob-protection来关闭保护。
阅读全文