参考

https://harttle.land/2016/03/22/purge-large-files-in-gitrepo.html

https://git-scm.com/docs/git-rev-list

https://git-scm.com/docs/git-filter-branch

https://git-scm.com/docs/git-verify-pack

该文章是自己操作时查找资料的实践内容,内容完全来自上面的作者。

前言

开发久了,有一些很老的东西,比如一开始没有拆分后来拆分到别的仓库的代码,编译的一些类库,或是后面删除掉的无用的模块,放在仓库中,每次clone,都非常大,可以通过git的一些方法查找,并且从仓库中删除。

特别注意

这是个很危险的动作,有可能会丢失数据,所以操作之前最好备份或是确保删除的不是关键信息。因为做了这个操作这些东西会永远从你的git仓库中删除,并且再也找不到任何信息,无法还原,所有的历史信息都会被重写。

删除一个文件

git filter-branch -f --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch <file>' --tag-name-filter cat -- --all

这里的命令就是把每一次提交都执行一次git rm -rf --cached --ignore-unmatch <file>的命令,这个命令就是把一个文件从git的跟踪仓库中删除。具体参考 https://www.cnblogs.com/studywithallofyou/p/11772684.html

--index-filter参数用来指定一条Bash命令,然后Git会检出(checkout)所有的提交, 执行该命令,然后重新提交。这样的话,我们就是在每个提交的记录下,调用命令,移除<file>,然后再提交,这个文件便从Git的所有记录中完全消失了。

删除一个文件夹

这个功能主要就是靠git rm的不同参数实现,也就是git filter-branch负责重写每次提交的历史,具体操作就是--index-filter指定的一条命令。上面的是删除一个文件,换成删除文件夹的,就可以指定删除某个文件夹下的内容。比如一开始我们提交了一个目录,里面都是一些编译生成的类库,后来不需要了,可以把它从历史中删掉。

git filter-branch -f --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch <folder>' --tag-name-filter cat -- --all

寻找大文件的ID

如果我们忘记了历史中哪些文件比较大,又想清理仓库,那么就可以用git verify-pack来查找。这个命令的作用就是列出来每次提交的内容中的详细信息,其中包含了提交内容的大小。

$ git verify-pack -v .git/objects/pack/*.idx
8fa15d279de33ce28a3289fd33951374084231e4 tree 135 137 144088922
a44a50b2ffb1f8283c8e64aafb8e7628249d7453 tree 33 43 144089059
b57d99f38fe22491e4a2d30c2b081ecb7bbb329c tree 99 97 144089102
2d4ffaffc11758d561ea1a6d57dd8ee17ee1d836 blob 644952 644959 144089199
8cf81ebfeec409f19e7a47a76517317f3bfa268d blob 695898 695871 144734158

-v(verbose)参数是打印详细信息。

输出的第一列是提交的index id,第二列表示文件(blob)或目录(tree),第三列是文件大小。 现在得到了所有的文件ID及其大小,然后我们就可以通过写一些脚本排序找出最大提交内容的index。

先按照第三列排序,并取最大的5条,然后打印出每项的第一列(index id):

$ git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5 | awk '{print$1}')"
f846f156d16f74243b67e3dabec58a3128744352
4a1546e732b2e2a352b7bf220c1a22ad859abf89
f72d04efe6d0b41b067f9fbbc62455f28d3670d2
49bdf300ddf57d1946bc9c6570d94a38ac9d6a50
9c073d4177af5d2e43ada41f92efb18d9462a536

这条命令的作用就是,显示到git仓库目录中过滤每一条提交index的信息,然后把这些信息中,按照第三行也就是大小排序,然后把最大的几个筛选出来,最后只打印对应的index id就可以了。

文件名与ID映射

上面我们仅仅得到的是提交的index,还是不知道这些里面哪些文件比较大,因为git rm需要指定文件名称。这时就需要git rev-list命令,这个命令的作用是列出来一个提交里面的内容信息。

$ git rev-list --objects --all
c252878ac09a3979a80520b82a71dc2dae4529f9
7bc7d05c6097063f531580ba4c32921464a6c456 _drafts
dcce26ed53fbb869dc7d5b71742d2f9e523bfe42 _layouts
414186c794a0d58695abb75c548bdbfec1de2763 _layouts/default.html
1934eeffe3d242375510dff28cffa6de6b3de367 _layouts/post.html
5f14647875f2177a6d37b8bfbcdb4629af595b64 _posts
6cdbb293d453ced07e6a07e0aa6e580e6a5538f4 _posts/---.md

--objects:列出该提交涉及的所有文件ID。
--all:所有分支的提交,相当于指定了位于/refs下的所有引用。

得到文件名列表

如果内容不多,你可以按照上面最大index的列表,然后一个个通过git rev-list来查看哪些文件比较大,一般也不是特别多,如果比较多或是想以后使用,可以再写一个脚本,排序出最大的文件列表。

$ git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5 | awk '{print$1}')"
f846f156d16f74243b67e3dabec58a3128744352 assets/img/recent-badge.psd
4a1546e732b2e2a352b7bf220c1a22ad859abf89 assets/img/album/me/IMG_0276.JPG
f72d04efe6d0b41b067f9fbbc62455f28d3670d2 assets/img/album/me/IMG_0389.JPG
49bdf300ddf57d1946bc9c6570d94a38ac9d6a50 assets/img/album/me/IMG_0813.JPG
9c073d4177af5d2e43ada41f92efb18d9462a536 assets/img/album/me/IMG_0891.JPG

上面的命令就是先通过rev-list列出所有index对应的文件信息,然后通过我们上面查找出的最大的提交index,通过grep过滤出来。这样就可以列出来上面查找的最大的提交index中所有的文件信息。

然后就可以从里面找出可以的文件删除了。删除完成后记着push到远程分支,如果push报错,可以通过下面命令,强制把所有分支的内容推送到远程。到此结束。

git push origin --force --all

清理git仓库的更多相关文章

  1. 使用BFG清除git仓库中的隐私文件或大文件

    使用git时间不长,在调机械臂项目的时候,由于对TwinCAT3和vs的机制不太了解,没有添加很好的忽略文件(.gitignore).造成git仓库包含了很多没有用的文件,例如vs的sdf文件,Twi ...

  2. Git仓库删除大文件

    Git仓库删除大文件 背景 当用Git久了,难免会手误或临时添加一些大文件到仓库中,即使以后添加进了.gitignore,甚至做了git rm,但是Git为了保证版本可回退,history pack里 ...

  3. 永久清理git中的历史大文件

    原文发布于:https://www.chenxublog.com/2019/05/26/remove-git-big-files.html 有写老的git仓库,因为当年的无知,不会用.gitignor ...

  4. Git 仓库拆分

    方案对比 subtree 使用命令 git subtree split -P dirPath -b branchName 将目标文件夹的代码都保存到指定分支.试了下,该方案虽然保留了 commit,但 ...

  5. 多本地代码工作点更新到2个远端GIT仓库

    摘要:本文介绍了笔者多个本地工作节点(地方)的多台电脑(PC/笔记本电脑)同步源码到2个远端的GIT(一个GITHUB国外强制公开,一个oschina国内可不公开). 作者:太初 转载说明:请指明原作 ...

  6. Git中如何利用生成SSH个人公钥访问git仓库

    Git中如何利用生成SSH个人公钥访问git仓库方法(这里以coding平台为例): 1. 获取 SSH 协议地址 在项目的代码页面点击 SSH 切换到 SSH 协议, 获得访问地址, 请使用这个地址 ...

  7. eclipse连接多个git仓库方法

    只需要在本地建立多个仓库就行,提交的时候一个本地仓库对应一个git仓库

  8. svn 版本迁移到 git 仓库

    1.拉取 svn代码并转成 git 版本 git svn fetch http://svn.qtz.com/svn/qtz_code/java/qtz_sm/project/qtz_sm -Auser ...

  9. git仓库的初始化

    关于git仓库的初始化和git push的操作 git init git remote add origin ssh://myserver.com/home/git/myapp.git git pul ...

随机推荐

  1. 浅谈 Vector

    目录 浅谈Vector 1.容器基本操作 2.vector 初始化 3.vector的赋值与swap 4.vector的增删改除 1.增加元素 2.访问元素 3.删除元素 4.元素的大小 浅谈Vect ...

  2. [python]兔子问题,斐波那契数列 递归&非递归

    假设一对幼年兔子需要一个月长成成年兔子,一对成年兔子一个月后每个月都可以繁衍出一对新的幼年兔子(即兔子诞生两个月后开始繁殖).不考虑死亡的情况,问第 N 个月时共有多少对兔子? 结果前几个月的兔子数量 ...

  3. springboot全局异常拦截源码解读

    在springboot中我们可以通过注解@ControllerAdvice来声明一个异常拦截类,通过@ExceptionHandler获取拦截类抛出来的具体异常类,我们可以通过阅读源码并debug去解 ...

  4. Spring MVC-从零开始-第一个控制器(不考虑命名规范)

    1.目录结构 (log4j.properties.mybatis-config.xml可忽略) 2.配置web.xml文件 <?xml version="1.0" encod ...

  5. Java入门学习笔记(全)

    JAVA https://zhuanlan.zhihu.com/p/21454718 引用部分实验楼代码,侵删 先通读文档 再亲自试标程 复习时自己再批注 1.a = b += c = -~d a = ...

  6. String 用法 简单API

    明天天梯赛选拔,怕不是STl忘到姥姥家去了,赶紧复习一下 构造str string s = "fuckyouRMA"; string s1(s, 2); de(s1); strin ...

  7. HashMap底层数据结构详解

    一.HashMap底层数据结构 JDK1.7及之前:数组+链表 JDK1.8:数组+链表+红黑树 关于HashMap基本的大家都知道,但是为什么数组的长度必须是2的指数次幂,为什么HashMap的加载 ...

  8. nginx的负载均衡实战

    前言 nginx是一个高性能的HTTP和反向代理的服务器.它有三个最基本的功能,一是当做web服务器.二是作为反向代理服务器.三是提供负载均衡(在反向代理基础上),由于它占有内存小,并发能力强,所以在 ...

  9. idea配置maven以及手动添加webapp目录

    idea配置maven 点击右下角Configure 点击settings 3 . 设置路径 设置自动导包 4 . 点击创建新工程 5 . 选择maven点击下一步 6 . 7 . 8 . 此时,创建 ...

  10. 复杂模型可解释性方法——LIME

    一.模型可解释性     近年来,机器学习(深度学习)取得了一系列骄人战绩,但是其模型的深度和复杂度远远超出了人类理解的范畴,或者称之为黑盒(机器是否同样不能理解?),当一个机器学习模型泛化性能很好时 ...