Git仓库删除大文件

背景

当用Git久了,难免会手误或临时添加一些大文件到仓库中,即使以后添加进了.gitignore,甚至做了git rm,但是Git为了保证版本可回退,history pack里面依然会存储这些对象,这个时候我们就要为Git仓库进行瘦身。

或者不是大文件的情况,有时我们需要删除掉一些敏感信息文件,比如password.txt,即使回退也无法找到敏感文件,要实现这个要求,也要对history pack进行清理。

清理主要做如下一些事情:

  1. 寻找想要彻底清理的文件路径
  2. 查询这个文件第一次出现的提交
  3. 从第一次出现的提交开始清理,重写之后的所有提交,保证该文件在history中完全抹除
  4. 清理掉相关的引用,以及log信息
  5. 重新打包所有对象
  6. 推送至远程仓库以应用更新

所以做完了清理之后,既能够保证Git还可以正常回溯,分支,tag,历史变更这些都还保留;又能够完全清理掉指定的文件。

操作思路

下面有2种途径达到目的

  1. 可以使用BFG工具,操作简单,链接为:https://rtyley.github.io/bfg-repo-cleaner/

  2. 如果喜欢自己倒腾,可以使用原生git命令组合实现,主要用到git filter-branch,其实BFG也是对该命令的封装

详细步骤

以第2种途径来达成目的,亲测可用,场景为 我在几个月前推送了一批镜像文件到仓库中,虽然git rm移除了,但history pack中依然保留了数据 。汗…

以下步骤均在工程根目录下操作

  1. 寻找大文件是哪些

镜像已经移除掉了,我需要寻找到它们曾经在哪里。以下命令罗列出整个仓库中前10个最大文件对象。该命令运行需要等待一段时间

$ git verify-pack -v .git/objects/pack/pack-43035f03d78ed39da647d4685e427bd126209bdb.idx | sort -k 3 -n | tail -10
e28b267b24de7d5b32ed2391669df8a72e24257d blob 162449408 62757122 757958127
c32c8b1da1c6283b250402aa31cde35051a52b3d blob 177733120 59785053 1360726301
711c9b581771981c54b4637497ceeb4bb23012bd blob 188976128 70107988 2347396900
d5cb26ac04328a255e922a24ea271ee50901c59d blob 196414976 74351707 1500585499
f93b48272597886796fc03d54e281f2403bea5ed blob 199080448 44716221 1455869278
247b35b36ef4c9f980c8cf967712788539980e5d blob 244180480 88897974 820715249
71848a6b5cb31639f8770553ddf6222573755d3d blob 414519296 140712921 100780869
d69f7af4727d15ee563aead6eff1d8baff61105d blob 1295518720 427812890 330145237
a3a36f25a9c3d610cb4d4eea381314ecf7b1510d blob 1324011520 443360428 909613223
c32670dfb49ae6a5948517fb6d19f78812a840ad blob 1802148352 617108853 1730288047

2.查找对应路径

发现e28b267b24de7d5b32ed2391669开头的对象最大,我们来看看它指代了哪个路径

$ git rev-list --objects --all | grep e28b267b24de7d5b32ed2391669
e28b267b24de7d5b32ed2391669df8a72e24257d backEnd/vendor/history/dockerimages/fabric-baseos

3.查找第一次出现该文件的log

从上个命令找到了大文件的曾经存在过的路径,现在查找log看看第一次提交该文件的版本号,结果列表里面最下面一个即为第一次,例如下面的722113f8a88。其实这一步不是必须的,因为清理可以从头清理到尾,全面覆盖。

$ git log --pretty=oneline --branches -- backEnd/vendor/history/dockerimages/fabric-baseos
486eac3085e25e9cec8c2de35c1e09cf79a5134e update
5fb74121be3fe311428068dd02837406a5d8f173 update
1380ead7f038a4b23add4fd64e9b66cb678cd6b5 commit something
a49db09fb148aabf51223d73fbcdb71e103610a0 update
722113f8a88e03cafebe7bbfcb6de20ffb068387 push

4.开始清理history

$ git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch backEnd/vendor/ILIOS/dockerimages/fabric-baseos' --prune-empty --tag-name-filter cat -- --all
Rewrite 6aeecaec3cfb419313bfb5516048b0979a6f284f (236/251) (11 seconds passed, rRewrite 2e5b34a51afb5a43f6b5d3e4400bfa0400629a4e (236/251) (11 seconds passed, rRewrite 914c89a1ea1e325f8be990c47cb71eaf88c29649 (236/251) (11 seconds passed, remaining 0 predicted)
WARNING: Ref 'refs/heads/branch1' is unchanged
WARNING: Ref 'refs/heads/master' is unchanged
Ref 'refs/heads/branch2' was rewritten
WARNING: Ref 'refs/remotes/origin/master' is unchanged
WARNING: Ref 'refs/remotes/origin/branch1' is unchanged
WARNING: Ref 'refs/remotes/origin/master' is unchanged
Ref 'refs/remotes/origin/branch2' was rewritten

5.清理所有废弃的引用

git verify-pack -v .git/objects/pack/pack-7b03cc896f31b2441f3a791ef760bd28495697e6.idx \
| sort -k 3 -n \
| tail -10
git rev-list --objects --all | grep 185ab8d
git log --pretty=oneline --branches -- spark-assembly-1.3.1-hadoop2.4.0.jar
git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch spark-assembly-1.3.1-hadoop2.4.0.jar' \
--prune-empty --tag-name-filter cat -- --all
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now
git count-objects -v
git push origin --force --all

参考文章:

  1. https://help.github.com/articles/removing-sensitive-data-from-a-repository/

  2. http://blog.csdn.net/zcf1002797280/article/details/50723783

  3. https://github.com/18F/C2/issues/439

  4. http://blog.csdn.net/vite_s/article/details/52315867

  5. http://blog.csdn.net/lwfcgz/article/details/49453375

Git仓库删除大文件的更多相关文章

  1. Git从库中移除已删除大文件

    写在前面大家一定遇到过在使用Git时,不小心将一个很大的文件添加到库中,即使删除,记录中还是保存了这个文件.以后不管是拷贝,还是push/pull都比较麻烦.今天在上传工程到github上,发现最大只 ...

  2. git忽略文件并删除git仓库中的文件

    问题描述 不慎在创建.gitignore  文件之前的时候将文件push到了 git仓库,即使之后在.gitignore文件中写入新的过滤规则,这些规则也不会起作用的,git依然会对所有git仓库中的 ...

  3. 如何永久删除git仓库中敏感文件的提交记录

    如何永久删除git仓库中敏感文件的提交记录 参考: 1. https://help.github.com/articles/remove-sensitive-data/

  4. git仓库删除所有提交历史记录

    stackoverflow原问题地址:http://stackoverflow.com/questions/13716658/how-to-delete-all-commit-history-in-g ...

  5. 【git】删除某个文件的所有历史记录,批量删除远程分支

    删除git某个文件的所有历史记录 git的目的就是版本控制,记录每一个版本的变动.然而有的时候我们往往希望从版本库中彻底删除某个文件,不再显示在历史记录中.例如不小心上传了一堆错误的文件,或者不小心上 ...

  6. git clean 删除忽略文件 和 未被跟踪文件及文件夹

    git clean 删除忽略文件 和 未被跟踪文件及文件夹 概念 首先我们需要认清 忽略的文件 和 未被跟踪的文件 忽略的文件:.gitignore 中忽略的文件 未被跟踪的文件:没有被忽略,但是还没 ...

  7. 如何使用 Git LFS 提交大文件?

    参考资料: An open source Git extension for versioning large files Git LFS的使用 如何使用 Git LFS 提交大文件? Git LFS ...

  8. 【转】Linux 中清空或删除大文件内容的五种方法(truncate 命令清空文件)

    原文: http://www.jb51.net/article/100462.htm truncate -s 0 access.log -------------------------------- ...

  9. 用rsync命令删除大文件夹

    删除大文件夹 rsync 命令做同步文件用的命令 我们可以借助其快速的运行 来对大文件夹删除:原来就是 新建一个空文件夹 然后把这个空文件夹同步到一个大文件夹下面: 这样会删除大文件夹下面的内容 是高 ...

随机推荐

  1. 流程控制:顺序结构: 代码默认从上到下依次执行 分支结构: 细分在分为如下 循环结构: while .. for ..

    # ### 流程控制: ''' 流程: 代码执行的过程 流程控制: 对代码执行的过程进行管控 顺序结构: 代码默认从上到下依次执行 分支结构: 细分在分为如下 循环结构: while .. for . ...

  2. #WEB安全基础 : HTTP协议 | 0x10 请求和响应报文重点结构及常见头部

    你需要认识一些常见的头部以及了解报文的详细结构 请求报文的请求行 GET/HTTP/1.1 响应报文的响应行 HTTP/1.1 200 OK 想必这些大家都知道了 请求 我访问一个页面 Host // ...

  3. Oracle 中 编写 function 和 procedure 的注意事项

    create or replace function sum_pro( v_a number, v_b number ) return number is -- v_result number(10) ...

  4. java操作git简单实现

    记录瞬间 import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.ListBranchCommand; import org.ecli ...

  5. 配置php环境的一个nginx.conf

    文件:nginx.conf 内容: #user  nobody;worker_processes  1; #error_log  logs/error.log;#error_log  logs/err ...

  6. C#调用java方法踩坑记

    首先,我的java代码写了一个遗传算法,这是我硕士毕业论文的核心算法,项目是基于C#的web项目.但是现在又不想用C#重写遗传算法代码,于是就想用C#去调用java的代码.在网上找了方法,一般有两种: ...

  7. iOS组件化之路(一)

    写在最前 从开始学写代码,胡乱的看书,不懂如何写第一个程序,到开始写出第一个程序,这段道路有些漫长.慢慢开始自己独立的去分析给出的需求,到如何实现,最初的想法只是仅仅实现,到后来懂得如何利用自己技术和 ...

  8. 再谈javascriptjs原型与原型链及继承相关问题

    什么是原型语言 只有对象,没有类;对象继承对象,而不是类继承类. “原型对象”是核心概念.原型对象是新对象的模板,它将自身的属性共享给新对象.一个对象不但可以享有自己创建时和运行时定义的属性,而且可以 ...

  9. JGit 切换分支

    //gitDir是git仓库的根目录,这个仓库必须是已clone好了 File file = new File(gitDir); Git git = Git.open(file); //切换分支, i ...

  10. liunx驱动----USB驱动

    现象:把usb设备接入电脑 1.Windows发现设备 2.跳出一个对话框提示安装驱动程序 问1:既然没有驱动程序,为什么了够知道是什么驱动了?? 答1:Windows里面已经有了usb总线驱动程序, ...