Git(七).git 文件夹瘦身,GitLab 永久删除文件
目录
- 一、问题背景
- 二、问题复现
- 2.1 新建项目
- 2.2 上传大文件
- 2.3 上传结果
- 三、解决方案
- 3.1 GitLab备份与还原
- 1)备份
- 2)还原
- 3.2 删除方式一:git filter-repo 命令【推荐】
- 1)安装
- 2)删除本地仓库文件
- 3)重新关联远程仓库
- 4)删除远程仓库文件
- 4)clean up 清理远程仓库
- 3.3 删除方式二:git branch-filter 命令【不推荐】
- 1)删除本地仓库文件
- 2)删除远程仓库文件
- 3)重新 repack 远程分支到本地
一、问题背景
由于项目在打 Docker 包的时候,需要将前端的包也打到 Docker 容器中,所以将前端包和前端的 Dockerfile 文件都放在了后端的 Git 目录下。
久而久之,由于前端包的更新迭代,Git 上面会一直保留前端包的历史版本,所以整个后端的 .git 越来越大,截至目前已经有 2.44G 了。每次有新的小伙伴加入 git 后都需要花很长时间来拉取代码,苦不堪言,而且 Jenkins 上面新建项目的拉取也会超时。
二、问题复现
2.1 新建项目
在 GitLab 上新建一个项目 my-test。

我们可以看到,新建好的项目,默认只有 20KB。

2.2 上传大文件
执行命令将项目克隆到本地:
git clone http://xxxx/xxx/xxx.git
此时,.git 文件夹大小为 30.7KB。
为了更加全面地测试,我们创建两个分支,并且分别上传文件。
分支、文件结构对应关系如下:
-
dev-test1分支| - pdf 文件夹
| - test_1.pdf 文件,12.8MB
| - test_2.pdf 文件,12.8MB
-
dev-test2分支| - pdf 文件夹
| - test_1.pdf 文件,12.8MB
| - test_2.pdf 文件,12.8MB
相关命令如下:
# 创建dev-test1分支
git checkout -b dev-test1
git add -A .
git commit -m "update test1"
git push origin dev-test1# 创建dev-test2分支
git checkout -b dev-test2
git add -A .
git commit -m "update test2"
git push origin dev-test2
2.3 上传结果
将大文件上传到 GitLab 后,仓库的大小如下:
.git:11.2MB
GitLab:11.3MB

三、解决方案
注意:操作前要保证是最新版本。
3.1 GitLab备份与还原
1)备份
在操作之前,我们要先备份 GitbLab 中的项目。最简单的方式就是直接将项目导出来。
在 GitLab 上打开项目,进入菜单 Settings -> General -> Advanced,点击 Expand 打开折叠。

点击 Export project。

可以看到提示,这个导出是一个异步的操作,当导出完毕之后会将通知发送到邮箱。

邮件中会有一个下载链接,点击链接下载,保存24小时。

下载后文件如下,文件名格式为:日期_时分秒_用户名_项目名.tar.gz

2)还原
点击首页的 New project。

选择 Import project。

选择 GitLab export。

输入项目名称,选择我们之前导出的 .tar.gz 文件,点击 Import project。

还原完毕,分支和大小都在。

3.2 删除方式一:git filter-repo 命令【推荐】
- git-filter-repo 官网: https://github.com/newren/git-filter-repo
- python 官网: https://www.python.org/
注意:
git-filter-repo工具需要依赖 Git 和 Python。
1)安装
# 安装(pip是Python自带的安装工具)
pip install git-filter-repo
# 查看版本
git-filter-repo --version
执行结果:

注意:git-filter-repo 需要在一个刚刚 clone 下来的仓库中进行操作,否则会操作失败。
Aborting: Refusing to destructively overwrite repo history since
this does not look like a fresh clone.
(expected at most one entry in the reflog for HEAD)
Please operate on a fresh clone instead. If you want to proceed
anyway, use --force.

2)删除本地仓库文件
git clone 到本地后立即执行如下命令:
(不要做切换分支等操作,否则会报错,删除重新克隆才行。)
# 模糊匹配,删除所有pdf文件(会同时删除pdf文件夹)
git filter-repo --path-glob '*.pdf' --invert-paths# 补充:精确匹配,仅删除pdf/test_1.pdf
git filter-repo --path-glob 'pdf/test_1.pdf' --invert-paths
执行结果如下:

git filter-repo 命令本身是用来将处理后的本地仓库重新推送到新的远程仓库用的,所以执行命令之后,查看 .git/config 配置文件,里面远程仓库的内容都被清空了:

执行之后,查看本地 .git 文件夹大小,从 11.2MB 直降至 32.8KB。
3)重新关联远程仓库
重新关联远程仓库的命令如下:
git remote add origin https://git.xxx.cn/acgkaka/my-test.git
4)删除远程仓库文件
执行如下命令,将本地仓库的改动强制推送到远程仓库即可。
git push --force origin --all
执行结果如下:

此时,GitLab 的远程仓库大小还是 11.2 MB,并无效果,别担心,还有最后一步操作。

4)clean up 清理远程仓库
做完上面的操作之后,等待半小时,是的,等待30分钟,因为 GitLab 不会清理半小时内提交的文件。
在 GitLab 上打开项目,进入菜单 Settings -> Repository -> Repository cleanup,点击 Expand 打开折叠。

在使用 clean up 时,需要提交一个文件,这个文件就是文件根目录下的 .git/filter-repo/commit-map。

可以看到提示,这个导出是一个异步的操作,当cleanup完毕之后会将通知发送到邮箱。

邮件中会说明 cleanup 后的仓库大小,为 0.1MB。

再去 GitLab 查看远程仓库大小,从 11.3MB 直降至 51KB,瘦身成功。

(经验证,这种方式删除掉的历史文件,即使有其他成员的本地仓库有未提交的版本,瘦身后依然可以正常提交,历史删除的文件也不会还原。)
3.3 删除方式二:git branch-filter 命令【不推荐】
注意: 目前经过尝试,发现 git branch-filter 虽然可以删除分支中的文件历史、提交记录,但是并不会减少 GitLab 中远程仓库的大小。
1)删除本地仓库文件
可以直接操作删除所有分支的文件,但是要注意必须保证所有分支都是最新代码才行。
也可以切换到具体分支,执行 git pull 拉取最新代码后,再进行删除,只要去除后面的 -- --all即可。
# 模糊匹配,删除所有pdf文件(会同时删除pdf文件夹)
git filter-branch --force --index-filter "git rm --cached --ignore-unmatch '*.pdf'" --prune-empty --tag-name-filter cat -- --all# 补充:精确匹配,仅删除pdf/test_1.pdf
git filter-branch --force --index-filter "git rm --cached --ignore-unmatch 'pdf/test_1.pdf'" --prune-empty --tag-name-filter cat -- --all
执行结果如下,可以看到 dev-test1 和 dev-test2 分支被重写了。

2)删除远程仓库文件
执行如下命令,将本地仓库的改动强制推送到远程仓库即可。
# 推送本地所有分支到远程
git push --force --all
执行结果如下,可以看到 dev-test1 和 dev-test2 分支被强制更新了。

我们可以去 GitLab 上面看下提交记录,"如果之前的提交只涉及被删除文件的话,对应提交记录就会被清空,如果提交中除了被删除文件之外还包含其他文件,那么提交记录和其他文件都会被保留,不受影响。

3)重新 repack 远程分支到本地
执行如下命令,删除 refs/original 文件夹,并重新更新远程仓库到本地。
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now
执行之后,查看本地 .git 文件夹大小,从 11.2MB 直降至 32KB。
再次声明,这种方式虽然可以删除分支中的文件历史、提交记录,但是并不会减少 GitLab 中远程仓库的大小。远程仓库大小依然为 11.3MB。(有大佬知道后面怎么处理的,欢迎评论补充)

整理完毕,完结撒花~ 🌻
参考地址:
1.使用 git-filter-repo 清理 git 历史记录,https://nyakku.moe/posts/2020/06/12/use-git-filter-repo-clean-git-history.html
2.利用git-filter-repo无缝迁移git项目,https://zhuanlan.zhihu.com/p/465078705
3.git: 如何减少.git文件的大小?https://blog.csdn.net/LOI_QER/article/details/107911115
4…git文件过大,github仓库瘦身,https://blog.csdn.net/luchengtao11/article/details/82531044
5.从Git仓库(GitLab)中彻底去除大文件,https://zhuanlan.zhihu.com/p/589903338
相关文章:
Git(七).git 文件夹瘦身,GitLab 永久删除文件
目录 一、问题背景二、问题复现2.1 新建项目2.2 上传大文件2.3 上传结果 三、解决方案3.1 GitLab备份与还原1)备份2)还原 3.2 删除方式一:git filter-repo 命令【推荐】1)安装2)删除本地仓库文件3)重新关联…...
多线程锁的升级原理是什么
在 Java 中,锁共有 4 种状态,级别从低到高依次为:无状态锁,偏向锁,轻量级锁和重量级锁状态,这几个状态会随着竞争情况逐渐升级。锁可以升级但不能降级。 多线程锁锁升级过程 如下图所示 多线程锁的升级过程…...
金山文档轻维表之删除所有行记录
目前脚本文档里面的只有删除行记录功能,但是需要指定ID值,不能实现批量删除,很多人反馈但是官方无回应,挺奇怪的 但是批量删除的需求我很需要,最后研究了一下,还是挺容易实现的 测试: 附上脚本…...
站坑站坑站坑站坑站坑
站坑站坑站坑站坑站坑站坑站坑...
在Vue中,你可以使用动态import()语法来动态加载组件
在Vue中,你可以使用动态import()语法来动态加载组件。动态导入允许你在需要时异步加载组件,这样可以提高应用程序的初始加载性能。 下面是一个使用动态导入加载组件的示例: <template> <div> <button click"loadComp…...
金蝶云星空表单插件获取日期控件判空处理(代码示例)
文章目录 金蝶云星空表单插件获取日期控件判空处理C#实现 金蝶云星空表单插件获取日期控件判空处理 C#实现 DateTime? deliveryDate (DateTime?)this.View.Model.GetValue("FApproveDate");//审核日期long leadtime 20;//天数if (!deliveryDate.IsNullOrEmpty()…...
通过xshell传输文件到服务器
一、user is not in the sudoers file. This incident will be reported. 参考链接: [已解决]user is not in the sudoers file. This incident will be reported.(简单不容易出错的方式)-CSDN博客 简单解释下就是: 0、你的root需要设置好密码 sudo …...
centos7.9编译安装python3.7.2
联网环境下编译安装python3.7.2,不联网则需要配置cnetos7.9离线源 下载解压软件包 [rootlocalhost ~]# tar -xf Python-3.7.3.tar.gz [rootlocalhost ~]# ls anaconda-ks.cfg Python-3.7.3 Python-3.7.3.tar.gz [rootlocalhost ~]# [rootlocalhost ~]# cd Pytho…...
【教3妹学编程-算法题】2913. 子数组不同元素数目的平方和 I
-----------------第二天------------------------ 面试官 : 好的, 我们再来做个算法题吧。平时工作中会尝试用算法吗, 用到了什么数据结构? 3妹 : 有用到, 用到了 bla bla… 面试官 : 好的, 题目是这样的࿱…...
是否会有 GPT-5 的发布?
本心、输入输出、结果 文章目录 是否会有 GPT-5 的发布?前言围绕 GPT-5 的信息OpenAI 期待增长GPT-5 - 到底是真的在训练,还是一个虚构的故事Sam Altman字里行间包含的信息我们在什么时候可以期待 GPT-5 的发布GPT-5 预计将在哪些方向努力GPT-5 在听觉领域GPT-5 在视频处理领…...
使用 Selenium Python 检查元素是否存在
像 Selenium 这样的自动化工具使我们能够通过不同的语言和浏览器自动化 Web 流程并测试应用程序。 Python 是它支持的众多语言之一,并且是一种非常简单的语言。 它的Python客户端帮助我们通过Selenium工具与浏览器连接。 Web 测试对于开发 Web 应用程序至关重要&am…...
const迭代器与模板构造函数
在自己实现C中list的时候,当实现const迭代器的时候,发现报错了,一直思考到现在 才发现是一个,很简单的问题,但是也让我有了一点感受,我在这里给大家分享一下。文章目录 1.当时遇到的问题2.解决方法3. 自己的…...
在Qt中解决opencv的putText函数无法绘制中文的一种解决方法
文章目录 1.问题2.查阅资料3.解决办法 1.问题 在opencv中,假如直接使用putText绘制中文,会在图像上出现问号,如下图所示: 2.查阅资料 查了一些资料,说想要解决这个问题,需要用到freetype库或者用opencv…...
【Linux】第六站:Centos系统如何安装软件?
文章目录 1.Linux安装软件的方式2.Linux的软件生态3. yum4. rzsz软件的安装与卸载5.yum如何知道去哪里下载软件? 1.Linux安装软件的方式 在linux中安装软件常用的有三种方式 源代码安装(我们还需要进行编译运行后才可以,很麻烦) …...
Istio 实战
文章目录 Istio流量管理分享会【1】什么是istio?【2】istio 可以干什么?【3】业务中的痛点?【4】istio 高级流量管理5.1 istio 组件介绍与原理5.2 sidercar何时注入?如何控制是否注入?5.3 查看sidecar 容器插入的容器中的iptablesDestination RuleVirtual ServiceGateways…...
【Midjourney入门教程4】与AI对话,写好prompt的必会方法
文章目录 1、语法2、单词3、要学习prompt 框架4、善用参数(注意版本)5、善用模版6、临摹7、垫图 木匠不会因为电动工具的出现而被淘汰,反而善用工具的木匠,收入更高了。 想要驾驭好Midjourney,可以从以下方面出发调整&…...
基于单片机的智能灭火小车设计
欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 技术交流认准下方 CSDN 官方提供的联系方式 文章目录 概要 一、整体设计方案1.1 整体设计任务1.2 整体设计要求1.3 系统整体方案设计1.3.1 整体模块设计1.3.2 整体设计方案选择…...
[Machine Learning][Part 7]神经网络的基本组成结构
这里我们将探索神经元/单元和层的内部工作原理。特别是,与之前学习的回归/线性模型和逻辑模型进行比较。最后接介绍tensorflow以及如何利用tensorflow来实现这些模型。 神经网络和大脑的神经元工作原理类似,但是比大脑的工作原理要简单的多。大脑中神经元的工作原理…...
精准测试:提高软件质量和用户满意度的利器
📢专注于分享软件测试干货内容,欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!📢交流讨论:欢迎加入我们一起学习!📢资源分享:耗时200小时精选的「软件测试」资…...
代碼隨想錄算法訓練營|第五十八天|583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结篇。刷题心得(c++)
目录 讀題 583. 两个字符串的删除操作 自己看到题目的第一想法 看完代码随想录之后的想法 72. 编辑距离 看完代码随想录之后的想法 583. 两个字符串的删除操作 - 實作 思路 代碼隨想錄思路 Code 72. 编辑距离 - 實作 思路 Code 编辑距离总结篇 判斷子序列 不同…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
