在git多分支repo仓库中彻底清除大文件
坑的由来
repo中不小心上传了许多测试生成的data。结果可想而知,原本只有代码的仓库突然间变得无比臃肿(或者是慢慢臃肿),从早期的几十MB,迅速飙升至1G.
到底发生了什么
早些时候我对git的原理并不是很了解,只是随着日常使用,终于开始理解git其实是一个指针指向一次提交的对象,当你在各个分支间切换的时候,指针就随之切换,版本也随之更改。
那么,git 是如何做到的能在各个版本间无缝切换的呢。即使long long ago的代码,只要来一句git reset --hard sesd54f54sdf5sd4sd5f 照样给你打回原形。
在相应的git文件夹里面 按下面组合键 可以看到隐藏的.git版本控制文件
ctrl+h

真相只有一个,那就是其实所有的版本,不管是否存在了多久,都仍然存在于硬盘里。所以你才可以任性地对代码为所欲为。然而,为所欲为也要付出代价。
代价就是,你删了几次,就会有几个快照存在于硬盘里。删一个大视频,表面上少了500M空间,实则增加了一次至少500M的历史提交记录,虽然现在的代码仓库里不再有这个视频,但是你试试du -sh .git看看.git 文件大小,是不是有惊喜?我在这儿体会的最恐怖的一次,见证了3个多G的.git
如何 解决
首先我们看看git相关文件占用的空间,运行
git count-objects -v

size-pack以千字节为单位表示,那么这里就有0.3G大小,这对代码仓库来说可是个恐怖的数字了。
那么让我们来找出罪魁祸首——到底是哪些大文件在混淆视听。
将所有含这些大文件的历史提交记录,一个不漏的找出来。
tail -30 表示 列举前30项
git rev-list --objects --all | grep -E `git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -30 | awk '{print$1}' | sed ':a;N;$!ba;s/\n/|/g'`

然后移除对该文件的引用 也就是 (tests_run_one.....后面一长串) (使用filter-branch去除大文件)
git filter-branch --force --index-filter "git rm --cached --ignore-unmatch 'tests_run_one.....后面一长串'" --prune-empty --tag-name-filter cat -- --all
进行repack
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin # 指示Git清除不需要的数据:
git reflog expire --expire=now --all && git gc --prune=now --aggressive
查看pack的空间使用情况
git count-objects -v
查看.git的实际大小
du -sh .git
强制把本地的分支(这里是master)更改推送到git服务器分支
git push origin --force --all
参数 origin 是远程仓库地址别名, 具体请参照 git remote -v 命令 查看选择
参数 --force 是强制推送, 这个参数表示强行覆盖远程仓库, 这个参数跟TNT一样危险不能乱用, 它可以简写为 -f
参数 --all 表示所有历史都要覆写, 当然我不知道这里的 “全部” 是多少, 教程里还提到了再提交一次 tags 的
强制push tags
git push origin --force --tags
需要把这一次的改动提交到远端仓库:
git push --force --verbose --dry-run
git push --force
依次执行以下命令
rm -rf .git/refs/original/ git reflog expire --expire=now --all git fsck --full --unreachable git repack -A -d git gc --aggressive --prune=now git push --force
注:这一步可能会收到错误,原因是protected的分支不能进行覆盖推送,可以首先把当前分支修改为unprotected,在仓库的设置中可以修改。
到此,大文件已经从仓库中清除了,重新拉一个仓库,速度变快了,可以看到仓库的体积已经变小了,注意:一定要重新拉取仓库。
最后告诉你的同事使用pull rebase而不是使用merge来更新他们分支。如果使用merge,他们本地的.git可能会覆盖你之前做的清理工作,再次push 的时候会让本地仓库再次引入到远程库中
或者告知他们下次 重新git clone
事实上有两种处理方法 参考gitlab官方文档 Reducing the repository size using Git
https://docs.gitlab.com/ee/user/project/repository/reducing_the_repo_size_using_git.html#reducing-the-repository-size-using-git
如果要使用BFG清除git仓库中的隐私文件或大文件参考下面
https://www.cnblogs.com/huipengly/p/8424096.html
当repo只有默认的master的时候 以上是可以完成需求的
实验证明 如果repo 有其他分支(除了master分支之外) 以上指令没有效果 也就是远程端 并没有减少库容量 因为分支没有得到push 实际上--all参数是失效的
首先创建本地
查看远程分支名称
git branch -r
远程先开好分支然后拉到本地( 本地分支会和远程分支建立一定关联)
git checkout -b Tests origin/Tests //检出远程的Tests分支到本地Tests
查看本地分支 是否切换到刚创建的
git branch
git gc
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all && git gc --prune=now --aggressive
强制 PUSH远程分支
git push origin Tests:Tests --force //推送本地的Tests(冒号前面的)分支到远程origin的Tests(冒号后面的)分支(没有会自动创建)
本文参考
https://blog.csdn.net/qq_40233736/article/details/86668768
https://kyriejoshua.github.io/jo.github.io/2016/07/17/how-to-clear-huge-files-in-git/
https://www.jianshu.com/p/17e5adf47da5
在git多分支repo仓库中彻底清除大文件的更多相关文章
- git 仓库中删除历史大文件
git 仓库中删除历史大文件 在git中增加了一个很大的文件,而且被保存在历史提交记录中,每次拉取代码都很大,速度很慢.而且用删除 提交历史记录的方式不是很实际. 以下分几个步骤介绍如何减小.git文 ...
- 由于github仓库中提前建立readme文件,导致git push报错error: failed to push some refs to 'git@github.com:
$ git push -u origin master To git@github.com:xxx/xxx.git ! [rejected] master -> master (fetch fi ...
- Linux系统中如何查找大文件或文件夹的方法
在Windows系统中,我们可以使用TreeSize工具查找一些大文件或文件夹,非常的方便高效,在Linux系统中,如何去搜索一些比较大的文件呢?下面我整理了一下在Linux系统中如何查找大文件或文件 ...
- git操作:删除仓库中的文件或目录
假定当前分支下,abc/123.txt需要从git仓库中删除: git .txt //删除abc目录下的123.txt文件,如果要删除abc目录,使用命令:git rm -r --cached abc ...
- 删除git中无用的大文件
推荐阅读:为什么你的 Git 仓库变得如此臃肿 有时候我们不小心提交了一些大文件上去,后来删除了,但是已经于事无补了,整个git的提及已经蹭蹭上去了. 这个时候怎么办呢? 1. 查看有哪些大文件(to ...
- 快速清理maven仓库中下载错误的文件
有时候使用pom文件下载依赖文件的时候突然网络异常,可能会出现依赖文件出现破损,导致怎么都不能使用,也没有重新下载. 之前解决办法是找到出现破损的文件并删除,让其重新下载,但是这样效率很低,也很难找到 ...
- 在python中逐行读取大文件
在我们日常工作中,难免会有处理日志文件的时候,当文件小的时候,基本不用当心什么,直接用file.read()或readlines()就可以了,但是如果是将一个10G大小的日志文件读取,即文件大于内存的 ...
- 使用git在github远程仓库中操作
在github上创建一个仓库,这一步参考廖雪峰老师的git教程,以及其他的一些准备工作略,我只记录几个重要的命令. 从其他github地址克隆项目 $ git clone git@github.com ...
- 忽略Git仓库中已经存在的文件
解决方案 使用Git bash进入到要忽略的文件所在的文件夹,执行以下命令即可 git update-index --assume-unchanged rebel.xml 参考 Ignore Git ...
随机推荐
- Web Worker 初探
什么是Web Worker? Web Worker 是Html5 提出的能够在后台运行javascript的对象,独立于其他脚本,不会影响页面的性能,也不会影响你继续对于页面进行操作.通俗点讲,就是后 ...
- js中判断空及获取当前服务的根路径
function isValue(o) { return (this.isObject(o) || this.isString(o) || this.isNumber(o) || this.isBoo ...
- 如何用ABP框架快速完成项目(14) - 结尾? 当然不是, 这只是开始!
此文当前版本号: 3 最近更新时间: 2018-12-9 04:52 本课程是方向性课程, 目的是避免南辕北辙. 方向盘一旦打正确, 还得需要以下文章去写好具体程序: 前面每篇文章里面的链接, 比 ...
- 解决在TP5中无法使用快递鸟的即时查询API
快递鸟的接口对接其实很简单,先去官网注册账号,登陆把基本信息填好,然后在产品管理中订购一下“物流查询”,免费,不过其他产品是收费,免费的有对接口调用频率限制,结合自己的应用流量够用就可以. 使用前复制 ...
- Synchronized 和 Lock 锁在JVM中的实现原理以及代码解析
一.深入JVM锁机制:synchronized synrhronized关键字简洁.清晰.语义明确,因此即使有了Lock接口,使用的还是非常广泛.其应用层的语义是可以把任何一个非null对象作为&qu ...
- Unity编译时找不到AndroidSDK的问题 | Unable to list target platforms(转载)
原文:http://www.jianshu.com/p/fe4c334ee9fe 现象 在用 Unity 编译 Android 平台的应用时,遇到 Unable to list target plat ...
- (后端)解决code唯一码(java)简便方法
public String next() { long appBootTimes = systemVariableService.getAppBootTimes(); return Long.toSt ...
- JavaScript中,JSON格式的字符串与JSON格式的对象相互转化
前言:JSON是一个独立于任何语言的数据格式,因此,严格来说,没有“JSON对象”和“JSON字符串”这个说法(然而”菜鸟教程“和”W3school“使用了“JSON对象”和“JSON字符串”这个说法 ...
- Spark MLlib线性回归代码实现及结果展示
线性回归(Linear Regression)是利用称为线性回归方程的最小平方函数对一个或多个自变量和因变量之间关系进行建模的一种回归分析. 这种函数是一个或多个称为回归系数的模型参数的线性组合.只有 ...
- Sql Server 按格式输出日期
SELECT dbo.fn_Data(getdate(),'yyyymmdd') CREATE FUNCTION [dbo].[fn_Data] (@date as datetime, @format ...