当前位置: 首页 > news >正文

记一次删除Git记录中的大文件的过程

最近在开发一个新应用,有一天在gitlab上clone代码的时候发现我的应用竟然有170+M,明明是一个全新的应用,代码都没有几行呢,为什么会有这么大呢?

后来经过了解Git的原理,解决了这个问题,把相关内容记录下来。分享一下。

Why

我的一个新应用竟然要170+M,这是打死我我也不会信的,于是就开始分析为什么会这么大。

step 1. 把代码拉到本地

git clone git@github.com:hollischuang/Architecture-Evolution.git

只是用这个地址举例,实际并不是这个项目。

step 2. 查看哪个文件占用的空间比较大

$cd Architecture-Evolution
$du -d 1 -h
 174M   ./.git
 264K   ./test
 96K    .

于是,发现是.git目录自己就占用了174M,了解Git的人都知道,.git目录是git自己生成的,记录了git仓库的相关信息的。看到这里其实并不难知道原因。

Git 维护着一个微型的文件系统,其中的文件也被称作数据对象。所有的数据对象均存储于项目下面的 .git/objects中。

经过我的验证,确实是.git/objects这个文件夹中的文件占了磁盘上174M的空间。

也就是说,只要我有一次将一个大文件误提交了,那么即使我后面把它删除了,但是,实际上在.git中,这个文件还是存在的,虽然我们可能再也不需要他了,但是他还在那里默默的存在着。。。

Git与大部分版本控制系统的差别是很大的,比如Subversion、CVS、Perforce、Mercurial 等等,使用的是“增量文件系统” (Delta Storage systems), 就是说它们存储每次提交(commit)之间的差异。Git正好与之相反,它会把你的每次提交的文件的全部内容(snapshot)都会记录下来。这会是在使用Git时的一个很重要的理念。

也就是说,如果我又一次把一个大文件务提交到git仓库中了,那么,下次提交时,即使你只改动了某个文件的一行内容,Git 也会生成一个全新的对象来存储新的文件内容。


因为以上两个特性,我回想起我的一次手残行为:
刚刚创建一个应用之后,我快速的写完代码,编译,运行,发现没啥问题之后,我准备先把他发布掉,于是我开始创建git仓库,并尝试把代码提交上去,这时我并没有创建.gitignore文件,我直接git add . git commit -m 'init' git push一气呵成的执行了熟悉的操作。

相信聪明的人已经发现了,逗比啊,我在编译代码之后,会有很多jar被我down到target目录下。我直接git add.把target下面的jar包,war包等这些也直接提交了。。。虽然后面我意识到,并且删除了这些文件,然后再次提交,但是由于刚我们说过的原因,这些文件依然占用着我的空间。。。

更多关于git的原理内容参见:Git 内部原理

How

问题已经定位到了,接下来就是要解决问题了。如果对git的原理及命令了解的比较多的话,这个问题还是比较好解决的,由于当时博主并不十分了解git的原理,所以做了一些知识储备之后才开始动手的。(Git 之术与道 — 对象、为什么你的 Git 仓库变得如此臃肿)

Step 1 查看哪些历史提交过文件占用空间较大

使用以下命令可以查看占用空间最多的五个文件:

git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5 | awk '{print$1}')"
rev-list命令用来列出Git仓库中的提交,我们用它来列出所有提交中涉及的文件名及其ID。 该命令可以指定只显示某个引用(或分支)的上下游的提交。

--objects:列出该提交涉及的所有文件ID。

--all:所有分支的提交,相当于指定了位于/refs下的所有引用。

verify-pack命令用于显示已打包的内容。

step 2. 重写commit,删除大文件

使用以下命令,删除历史提交过的大文件:

git filter-branch --force --index-filter 'git rm -rf --cached --ignore-unmatch big-file.jar' --prune-empty --tag-name-filter cat -- --all

上面脚本中的big-file.jar请换成你第一步查出的大文件名,或者这里直接写一个目录。

filter-branch命令可以用来重写Git仓库中的提交

--index-filter参数用来指定一条Bash命令,然后Git会检出(checkout)所有的提交, 执行该命令,然后重新提交。

–all参数表示我们需要重写所有分支(或引用)。

在重写提交的过程中,会有以下日志输出:

Rewrite 6cdbb293d453ced07e6a07e0aa6e580e6a5538f4 (266/266)
# Ref 'refs/heads/master' was rewritten

如果显示 xxxxx unchanged, 说明repo里没有找到该文件, 请检查路径和文件名是否正确,重复上面的脚本,把所有你想删除的文件都删掉。

step 3. 推送修改后的repo

以强制覆盖的方式推送你的repo, 命令如下:

git push origin master --force

step 4. 清理和回收空间

虽然上面我们已经删除了文件, 但是我们的repo里面仍然保留了这些objects, 等待垃圾回收(GC), 所以我们要用命令彻底清除它, 并收回空间,命令如下:

rm -rf .git/refs/original/
git reflog expire --expire=now --all
git gc --prune=now

至此,我们已经彻底的删除了我们不想要的文件。

原文链接

相关文章:

  • CoreOS那些事之Rkt容器尝鲜(上)
  • 入学人数突破1000人! 阿里云大学云学院,开启创新育才实践之路!
  • Opencv笔记(十六)——认识轮廓
  • md5学习
  • 批量kill 某个用户session
  • Failed to create AppDomain 'xxx'. Exception has been Failed to create AppDomain
  • JWT究竟是什么呢?
  • Win#password;;processon #clone;;disassemble;;source find
  • PHP全栈开发(三):CentOS 7 中 PHP 环境搭建及检测
  • V神新论文|STARKs III: Into the Weeds(下)
  • Docker学习笔记三:Docker镜像image
  • python学习之老男孩python全栈第九期_day029知识点总结——configparser模快、logging模块...
  • python爬虫知识点总结(二十三)Scrapy中Download Middleware的用法
  • eclipse常用图标(类相关)及常用UML类图元素符号示意
  • dns相关
  • 分享的文章《人生如棋》
  • IOS评论框不贴底(ios12新bug)
  • Java 9 被无情抛弃,Java 8 直接升级到 Java 10!!
  • JavaScript 一些 DOM 的知识点
  • Python socket服务器端、客户端传送信息
  • SegmentFault 2015 Top Rank
  • SpingCloudBus整合RabbitMQ
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • 悄悄地说一个bug
  • 巧用 TypeScript (一)
  • 适配iPhoneX、iPhoneXs、iPhoneXs Max、iPhoneXr 屏幕尺寸及安全区域
  • 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  • 一加3T解锁OEM、刷入TWRP、第三方ROM以及ROOT
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • AI又要和人类“对打”,Deepmind宣布《星战Ⅱ》即将开始 ...
  • ​HTTP与HTTPS:网络通信的安全卫士
  • # 计算机视觉入门
  • #stm32整理(一)flash读写
  • #传输# #传输数据判断#
  • $.ajax中的eval及dataType
  • ( )的作用是将计算机中的信息传送给用户,计算机应用基础 吉大15春学期《计算机应用基础》在线作业二及答案...
  • (aiohttp-asyncio-FFmpeg-Docker-SRS)实现异步摄像头转码服务器
  • (env: Windows,mp,1.06.2308310; lib: 3.2.4) uniapp微信小程序
  • (ibm)Java 语言的 XPath API
  • (Oracle)SQL优化技巧(一):分页查询
  • (webRTC、RecordRTC):navigator.mediaDevices undefined
  • (附源码)php投票系统 毕业设计 121500
  • (附源码)ssm户外用品商城 毕业设计 112346
  • (机器学习的矩阵)(向量、矩阵与多元线性回归)
  • (全注解开发)学习Spring-MVC的第三天
  • (算法)求1到1亿间的质数或素数
  • (一)eclipse Dynamic web project 工程目录以及文件路径问题
  • (转)JVM内存分配 -Xms128m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m
  • (转)程序员技术练级攻略
  • (转)可以带来幸福的一本书
  • **CI中自动类加载的用法总结
  • .mysql secret在哪_MYSQL基本操作(上)
  • .NET 4.0网络开发入门之旅-- 我在“网” 中央(下)
  • .NET 表达式计算:Expression Evaluator
  • .net 流——流的类型体系简单介绍