Git使用:大体积的历史commit无法推送到远程仓库的解决方案
场景:把本地仓库全量推送到远程的空仓库,保留提交历史,所有分支,所有tag;
大部分代码托管服务都会有免费推送的限制(如gitlab,
如上的失败,可以通过git 命令,批量改写提交历史来解决;
本文以在GitHub建立远程的空仓库为例,介绍本地仓库推送至远程仓库,保留提交历史,所有分支,所有tag,和批量改写提交历史的步骤,以解决『大体积的历史commit无法推送到远程仓库』的问题;
1 新建远程的空仓库
不要添加默认的README,仓库必须为空,否则会push失败;
2 改写本地仓库的远程目标仓库
cd <你的本地仓库路径>/ # 查看远程目标 git remote -v # 删除远程目标 git remote rm origin # 或者,你也可以更改原有的远程目标的名字 # git remote rename origin old-origin git remote -v # 添加1.1节中新建的远程仓库 git remote add origin git@github.com:<你的GitHub用户名>/<你的仓库名>.git git remote -v
3 推送所有分支/tag到远程
# 推送所有分支到名为origin的远程目标 git push -u origin --all # 和 git push --set-upstream origin --all 是一样的 # 推送所有tag到名为origin的远程目标 # !! 推送tags仍然失败了,推测是需要切到每一个tag,每一个tag都需要删除大文件的历史;考虑到全量tags的推送并不重要,作为后续的TODO; git push -u origin --tags # (可选的)你也可以,更改当前的分支名,并单独推送该分支到远程目标的某一分支 # 更改当前分支名为main git branch -M main # 把当前分支推送到远程的main分支 git push -u origin main
4 批量改写提交历史
在3节,git push -u origin --all
时,报错;
日志中提示,有提交大于了100MB的限制;
4.1 找到大体积的文件
find . -type f -exec du -h {} + | sort -h | tail -n20
示例输出:
uav@uav-G5-5500:/tmp/**$ find . -type f -exec du -h {} + | sort -h | tail -n20 ... 93M ./tests/data/Tunnel.pcap 205M ./tests/data/highway.pcap 256M ./.git/objects/pack/pack-c3cfcbe650b543caf1143271c04fa51e377314b5.pack 1019M ./.git/objects/pack/pack-d77ef04279c83d523f00d9b0df8674cae91ae0a2.pack
推测大体积的提交历史大概率是包含了pcap文件;
4.2 删除提交历史中的大体积文件
# 查看本地分支列表; git branch # 逐个切换到每个分支,在每个分支都要执行更改提交历史的操作; # !! 没有找到1次变更所有分支历史的方法,TODO; git checkout master git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch *.pcap' # ... 同样操作其他分支;
控制台的输出,如下:
# ... Rewrite 431b95ba4b145f70bb13fb4d5dbc11854d4d1283 (799/808) (67 seconds passed, remaining 0 predicted) rm 'tests/data/16_highway.pcap' rm 'tests/data/Tunnel.pcap' rm 'tests/data/64.pcap' rm 'tests/data/128.pcap' Rewrite e447e530142024c1048aa3b782e6645238422b76 (799/808) (67 seconds passed, remaining 0 predicted) rm 'tests/data/16_highway.pcap' rm 'tests/data/Tunnel.pcap' rm 'tests/data/64.pcap' rm 'tests/data/128.pcap' # 提示,历史改写成功; Ref 'refs/heads/master' was rewritten
需要注意的地方:
# 使用*.pcap进行匹配,如果使用.pcap,会匹配失败,显示分支未修改; git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch .pcap' WARNING: git-filter-branch has a glut of gotchas generating mangled history rewrites. Hit Ctrl-C before proceeding to abort, then use an alternative filtering tool such as 'git filter-repo' (https://github.com/newren/git-filter-repo/) instead. See the filter-branch manual page for more details; to squelch this warning, set FILTER_BRANCH_SQUELCH_WARNING=1. Proceeding with filter-branch... Rewrite e447e530142024c1048aa3b782e6645238422b76 (802/808) (67 seconds passed, remaining 0 predicted) # 提示分支未修改; WARNING: Ref 'refs/heads/master' is unchanged
4.3 再次推送
参考3节;
git push -u origin --all
5 使用LFS推送大文件
LFS(Large File Storage)通过把大文件存储放在Git仓库之外,并在Git仓库中保存文件的指针,从而实现对大文件的管理;
如果仍然有大文件的推送需求,可以使用LFS,TODO;
x 参考
一些常用的git命令:
Git命令 | 作用 | 备注 |
---|---|---|
git config -l | 列出当前git仓库或全局配置的所有配置项及其值; | 仓库级别的配置项存储在仓库的.git/config文件中;全局级别的配置项存储在您用户目录下的.gitconfig文件中; |
git pull github main | 从名为github的远程仓库的main分支拉取最新的修改,并将其合并到当前所在的本地分支中; | 如果存在冲突,需要手动解决冲突后再进行提交; |
x.1
x.2
x.3
x.4
x.5
x.6
x.7
x.8
x.9
x.10