坑的由来

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仓库中彻底清除大文件的更多相关文章

  1. git 仓库中删除历史大文件

    git 仓库中删除历史大文件 在git中增加了一个很大的文件,而且被保存在历史提交记录中,每次拉取代码都很大,速度很慢.而且用删除 提交历史记录的方式不是很实际. 以下分几个步骤介绍如何减小.git文 ...

  2. 由于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 ...

  3. Linux系统中如何查找大文件或文件夹的方法

    在Windows系统中,我们可以使用TreeSize工具查找一些大文件或文件夹,非常的方便高效,在Linux系统中,如何去搜索一些比较大的文件呢?下面我整理了一下在Linux系统中如何查找大文件或文件 ...

  4. git操作:删除仓库中的文件或目录

    假定当前分支下,abc/123.txt需要从git仓库中删除: git .txt //删除abc目录下的123.txt文件,如果要删除abc目录,使用命令:git rm -r --cached abc ...

  5. 删除git中无用的大文件

    推荐阅读:为什么你的 Git 仓库变得如此臃肿 有时候我们不小心提交了一些大文件上去,后来删除了,但是已经于事无补了,整个git的提及已经蹭蹭上去了. 这个时候怎么办呢? 1. 查看有哪些大文件(to ...

  6. 快速清理maven仓库中下载错误的文件

    有时候使用pom文件下载依赖文件的时候突然网络异常,可能会出现依赖文件出现破损,导致怎么都不能使用,也没有重新下载. 之前解决办法是找到出现破损的文件并删除,让其重新下载,但是这样效率很低,也很难找到 ...

  7. 在python中逐行读取大文件

    在我们日常工作中,难免会有处理日志文件的时候,当文件小的时候,基本不用当心什么,直接用file.read()或readlines()就可以了,但是如果是将一个10G大小的日志文件读取,即文件大于内存的 ...

  8. 使用git在github远程仓库中操作

    在github上创建一个仓库,这一步参考廖雪峰老师的git教程,以及其他的一些准备工作略,我只记录几个重要的命令. 从其他github地址克隆项目 $ git clone git@github.com ...

  9. 忽略Git仓库中已经存在的文件

    解决方案 使用Git bash进入到要忽略的文件所在的文件夹,执行以下命令即可 git update-index --assume-unchanged rebel.xml 参考 Ignore Git ...

随机推荐

  1. Flask 系列之 SQLAlchemy

    SQLAlchemy 是一种 ORM 框架,通过使用它,可以大大简化我们对数据库的操作,不用再写各种复杂的 sql语句 了. 说明 操作系统:Windows 10 Python 版本:3.7x 虚拟环 ...

  2. 关于Facebook和Google+授权登录

    实际中遇到需要Facebook和Google+等第三方授权登录自己的Web应用(可能还有Android和IOS的手机应用),本质上都是JS SDK的官方应用.这时候不得不去他们官方查看文档. 注:一下 ...

  3. Docker多步构建更小的Java镜像

    译者按: 最新版Docker将支持多步构建(Multi-stage build),这样使用单个Dockerfile就可以定义多个中间镜像用于构建,测试以及发布等多个步骤,并且有效减小最终镜像的大小. ...

  4. nginx部署与安装

    1.在学习ngnix的时候,免不了需要进行安装,安装其实很简单,一个shell脚本就可以搞定可以参考如下 使用root用户执行nginx-install.sh脚本即可,脚本如下: #!/bin/bas ...

  5. CSS3 画基本图形,圆形、椭圆形、三角形等

    CSS3圆角#css3-circle{ width: 150px; height: 150px; border-radius: 50%; }CSS3 椭圆形css3 radius#css3-elips ...

  6. CSS3效果:5种预载动画效果

    实现如图所示的动画效果: 预载动画一:双旋圈 在两个不同方向旋转的圆圈.我们对内圈的转速定义了一个CSS代码,即内圈比外圈的速率快2倍.实现如图所示: html代码: <body style=& ...

  7. RabbitMQ 在 web 页面 创建 exchange, queue, routing key

    这里只是为了展示, 在实际开发中一般在消费端通过 注解来自动创建 消费端: https://www.cnblogs.com/huanggy/p/9695934.html 1, 创建 Exchange ...

  8. 数据筛选和API优化

    筛选数据 需求:如果数据库中存在OrderNum相同,且IsDefault不同的记录,那么IsDefault值为0的记录将替换值为1的记录(IsDefault值为1的记录不展示). 由于查出来的数据不 ...

  9. Salesforce 应用生命周期管理

    应用程序生命周期管理 一个Salesforce系统可以有多个版本,最常见的有: production版本:终端用户实际使用的版本 sandbox版本:沙盒环境,用于开发.测试等 在对Salesforc ...

  10. Python date,datetime,time等相关操作总结

    date,datetime,time等相关操作总结   by:授客 QQ:1033553122 测试环境: Python版本:Python 3.3.2 代码实践: __author__ = '授客' ...