坑的由来

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. Android Studio 学习(一)

    XML给元素定义ID 定义id android:id="@+id/button_1" 引用id id/id_name 解决Failed to load Appcompat Acti ...

  2. pullMsg有感

    开发功能过程中,始终会有些东西是确认的,比如美丑.业务是否合理.对错. 如果明知道不合理,却按照已有规定.框架.设计去开发,其实是不够职业. 好的做法是朝对的方向去push,并落地: 次之是去push ...

  3. 创建Aurelia项目

    什么是Aurelia? Aurelia 是一个新的开源的,基于web标准的mvvm框架,是一个现代化的js模块的集合. Aurelia提供了丰富的plugin,例如国际化,验证,模态框,UI可视化等. ...

  4. 学用纯CSS3打造可折叠树状菜单

    CSS执行顺序与优先权的问题其实就是一个冲突解决的问题,当同一个元素(或内容)被CSS选择符选中时,就要按照优先权取舍不同的CSS规则,这其中涉及到的问题其实很多.首先就是CSS规则的specific ...

  5. 微信小程序 table 简单测试

    <view class='AutoTable'> <view id='AutoTableItem'> <block wx:for="{{array}}" ...

  6. CSS制作镂空字体

    1.效果图 2.html内容: <!doctype html><html lang="en"><head> <meta charset=& ...

  7. springmvc 获取请求头信息

    @PostMapping("/test/post") public void post(@RequestBody String params, @RequestHeader(req ...

  8. Android笔试题三

    1.java堆得Young区由哪些组成: Java堆由Perm区和Heap区组成,Heap区由Old区和New区(也叫Young区)组成,New区由Eden区.From区和To区(Survivor)组 ...

  9. 想让安卓app不再卡顿?看这篇文章就够了

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由likunhuang发表于云+社区专栏 实现背景 应用的使用流畅度,是衡量用户体验的重要标准之一.Android 由于机型配置和系统的 ...

  10. Android-垂直滑动的ViewPager

    该ViewPager和正常的ViewPager的使用方式是一样的,只不过是垂直滑动的. 下面是这个ViewPager的代码 /** * 垂直滑动的ViewPager */ public class V ...