问题根源分析
当 Git 推送失败并出现 error: RPC failed; HTTP 500
或 fatal: the remote end hung up unexpectedly
错误时,通常是由于以下原因:
- 历史提交中包含大文件(>100MB)
- 当前提交包含大文件
- 大文件已被删除但历史记录仍保留
- 网络不稳定导致大文件传输中断
解决方案全景图

场景一:不需要保留大文件
彻底清除历史中的大文件(推荐方案)
步骤 1:安装必要工具
-
安装 Python
-
下载并安装 Python 3.x(建议选择最新版本,如3.11)。
-
安装时勾选 "Add Python to PATH"。
-
验证安装:
bashpython --version
-
-
安装
git filter-repo
-
打开命令提示符(CMD)或 PowerShell,运行:
bashpip install git-filter-repo
-
验证安装:
bashgit filter-repo --version
-
步骤 2:定位大文件
bash
git rev-list --objects --all \
| git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' \
| awk '/^blob/ { if ($3 > 100000000) print $4 }' \
| sort -u
步骤 3:清除历史文件
bash
# 示例:清除 bigfile.zip
# filter-repo
git filter-repo --path bigfile.zip --invert-paths --force
步骤 4:清理并推送
bash
git gc --aggressive --prune=now
git push origin master --force
备选方案( 无需安装工具)
bash
# 清除特定文件的历史
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch path/to/largefile" \
--prune-empty --tag-name-filter cat -- --all
# 清理仓库
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
git reflog expire --expire=now --all
git gc --prune=now --aggressive
场景二:需要保留大文件
方案一:使用 Git LFS(推荐)
步骤 1:安装 Git LFS
bash
# Linux
curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash
sudo apt install git-lfs
# macOS
brew install git-lfs
# Windows
choco install git-lfs
步骤 2:初始化 LFS
bash
git lfs install
git lfs track "*.zip" "*.psd" "*.bin"
git add .gitattributes
步骤 3:迁移历史文件
bash
# 迁移特定文件类型
git lfs migrate import --include="*.zip" --everything
# 迁移特定文件
git lfs migrate import --include="path/to/bigfile.zip" --everything
步骤 4:推送更改
bash
git push origin master --force
方案二:云存储 + Git 子模块(企业级方案)
- 将大文件上传到云存储(AWS S3, Google Cloud Storage 等)
- 创建包含下载脚本的仓库
- 在主项目中添加子模块
bash
# 添加云存储仓库作为子模块
git submodule add https://github.com/yourcompany/assets-repo assets
# 更新子模块
git submodule update --init --recursive
场景三:大文件在历史中存在但当前已删除
最佳实践:重写历史清除
bash
# 1. 创建备份分支
git checkout -b backup-before-clean
# 2. 使用 BFG 工具清除
java -jar bfg.jar --delete-files bigfile.zip .
# 3. 清理仓库
git reflog expire --expire=now --all
git gc --prune=now --aggressive
# 4. 强制推送
git push origin master --force
替代方案:浅层克隆
bash
# 创建不含历史的新分支
git checkout --orphan new-branch
git add .
git commit -m "Initial commit without history"
# 推送到新分支
git push origin new-branch
# 在远程设置新分支为默认
网络优化方案
解决连接问题
bash
# 增加 POST 缓冲区大小
git config http.postBuffer 524288000 # 500MB
# 降低压缩级别
git config core.compression 0
# 使用 SSH 替代 HTTPS
git remote set-url origin [email protected]:user/repo.git
# 启用长连接
git config http.version HTTP/1.1
分块推送大仓库
bash
# 每次推送部分历史
git push origin master --thin-pack --depth=100
预防措施
添加预提交钩子
创建 .git/hooks/pre-commit
:
bash
#!/bin/sh
MAX_SIZE=104857600 # 100MB
for file in $(git diff --cached --name-only); do
size=$(git cat-file -s :$file 2>/dev/null || ls -l $file | awk '{print $5}')
if [ $size -gt $MAX_SIZE ]; then
echo "错误: $file 超过100MB ($size bytes)"
echo "使用 'git reset HEAD $file' 取消暂存"
exit 1
fi
done
设置权限:chmod +x .git/hooks/pre-commit
永久配置
bash
# 禁止大文件
echo '*.zip filter=lfs diff=lfs merge=lfs -text' >> .gitattributes
# 设置全局忽略
git config --global core.excludesfile ~/.gitignore_global
echo "*.log" >> ~/.gitignore_global
echo "*.tmp" >> ~/.gitignore_global
不同场景推荐方案
场景 | 推荐方案 | 优点 | 缺点 |
---|---|---|---|
个人项目 不需要历史大文件 | git filter-repo |
永久解决,仓库瘦身 | 重写历史 |
团队协作 需要保留大文件 | Git LFS | 版本控制大文件 | 需要LFS支持 |
企业项目 超大文件管理 | 云存储+子模块 | 无仓库膨胀 | 增加架构复杂度 |
历史大文件 当前已删除 | BFG工具 | 快速清除历史 | 需要Java环境 |
操作后验证
bash
# 检查仓库大小
git count-objects -vH
# 测试推送
git push --dry-run origin master
# 验证历史
git log --all --find-object=<大文件哈希>
注意事项
- 强制推送风险 :
--force
会覆盖远程历史,确保团队协调 - 备份优先 :操作前执行
git clone --mirror
创建完整备份 - LFS成本:Git LFS 可能有存储和带宽限制
- 团队通知:历史重写后通知成员重新克隆仓库
通过以上方案,您可以彻底解决 Git 大文件导致的推送问题,并根据实际需求选择最适合的处理方式。