使用BFG缩减Git仓库体积后分支分歧及大文件重复引入问题
问题背景
假设存在一个含README.md的测试仓库,流程如下:
- 在其他分支提交大文件并向
master发起PR - 通过另一个PR合并移除大文件,但Git对象中仍遗留大体积
.pack文件 - 使用BFG工具清理该文件,步骤为:
- 下载
bfg.jar - 用
--mirror参数克隆仓库(否则远程分支无法更新) - 执行命令:
java -jar path/to/bfg.jar --delete-files 'somelargefile.zip' - 执行命令:
git reflog expire --expire=now --all && git gc --prune=now --aggressive - 执行命令:
git push --force
- 下载
清理后远程仓库恢复整洁,但协作成员的本地仓库仍保留带大.pack文件的分支。拉取最新代码时会出现「You have divergent branches and need to specify how to reconcile them」错误,无论选择合并/变基/快进,后续提交都会再次引入大文件,形成循环。
本地仓库修复方案(无需重新克隆)
针对本地已有问题分支的情况,按以下步骤操作:
重置本地分支到远程最新状态
切换到受影响的分支(比如master),执行:git fetch origin git reset --hard origin/master该操作会丢弃本地分支的所有未提交修改,强制对齐远程仓库的最新干净版本。
清理本地Git冗余对象
执行本地GC命令彻底清除残留的大文件对象:git reflog expire --expire=now --all git gc --prune=now --aggressive删除本地废弃分支
如果之前提交大文件的分支已无保留必要,直接删除本地对应的分支:git branch -D old-large-file-branch避免后续误操作再次合并该分支。
用Git钩子阻止大文件提交(含历史残留)
可以通过两种钩子从源头拦截大文件:
1. 本地预提交钩子(pre-commit)
在本地仓库的.git/hooks/目录下创建pre-commit文件(若有.sample后缀则去掉),写入以下内容:
#!/bin/sh # 设置允许的最大文件大小(单位:字节,这里设为10MB) MAX_SIZE=$((10*1024*1024)) # 检查即将提交的所有新增/修改文件 for FILE in $(git diff --cached --name-only); do if [ -f "$FILE" ]; then FILE_SIZE=$(stat -c%s "$FILE") if [ "$FILE_SIZE" -gt "$MAX_SIZE" ]; then echo "错误:文件 $FILE 大小超过 $MAX_SIZE 字节,禁止提交" exit 1 fi fi done # 扫描所有历史对象,防止通过变基/合并引入残留大文件 git rev-list --all --objects | grep -E "^[0-9a-f]{40} .*$" | while read -r HASH PATH; do OBJECT_SIZE=$(git cat-file -s "$HASH") if [ "$OBJECT_SIZE" -gt "$MAX_SIZE" ]; then echo "错误:历史对象中发现大文件 $PATH(大小 $OBJECT_SIZE 字节),禁止提交" exit 1 fi done exit 0
然后给文件添加执行权限:
chmod +x .git/hooks/pre-commit
2. 远程预接收钩子(pre-receive)
在远程仓库的hooks/目录下创建pre-receive文件,写入以下内容:
#!/bin/sh MAX_SIZE=$((10*1024*1024)) while read -r OLD_REF NEW_REF REF_NAME; do # 检查推送的所有提交中的文件 git rev-list "$OLD_REF..$NEW_REF" --objects | grep -E "^[0-9a-f]{40} .*$" | while read -r HASH PATH; do OBJECT_SIZE=$(git cat-file -s "$HASH") if [ "$OBJECT_SIZE" -gt "$MAX_SIZE" ]; then echo "错误:推送的提交中包含大文件 $PATH(大小 $OBJECT_SIZE 字节),拒绝接收" exit 1 fi done done exit 0
添加执行权限:
chmod +x hooks/pre-receive
内容的提问来源于stack exchange,提问作者user1735921
相关产品推荐
相关产品推荐

