Git永久删除文件和历史记录

造成你想从git存储库中永久删除文件和历史记录的可能有:

  • 你不小心将一个不该加入版本管理的文件加了进去,敏感数据或大文件或别的没用的文件;
  • 你不小心将一个涉及到破解某著名软件的文章加了进Github仓库,这时你就会收到github官方的邮件来提醒你需要完全删除该文件,不然就会遭到git仓库被封禁。
  • 你希望将敏感数据或无用文件从版本库中永久删除不留痕迹,不仅仅在版本历史里看不出来,还要把它占用的空间也释放出来。

参考官方链接,github 的帮助文档:

https://help.github.com/articles/remove-sensitive-data

很详细的说明了步骤和提供了一种使用BFG工具的思路(更便利)

这里我只说使用git命令的方式,以windows平台下为例,linux类似做法:

使用filter-branch

注意: 如果在存储更改后运行git filter-branch,则无法使用其他存储命令检索更改。

在运行git filter-branch之前,建议取消所做的任何更改。要unstash最后一组隐藏的更改,运行git stash show -p | git apply -R。有关更多信息,请参阅https://git-scm.com/book/en/v1/Git-Tools-Stashing。

演示如下:

进入git存储仓库,运行以下命令,用要删除文件的相对路径(而不仅仅是文件名)替换PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA

这行长命令的参数做到的事是:

  • 强制Git处理(但不检出)每个分支和标记的全部历史;

  • 删除指定的文件,以及由此生成的任何空提交;

  • 覆盖你现有的tags

    $ git filter-branch --force --index-filter \
    'git rm --cached --ignore-unmatch PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA' \
    --prune-empty --tag-name-filter cat -- --all

    其中, PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA 就是你要删除的文件的相对路径(相对于git仓库的根目录), 替换成你要删除的文件路径即可. 注意一点,这里的文件或文件夹,如果以 '/' 开头,则文件或文件夹会被认为是从 git 的安装目录开始。

    如果你要删除的目标不是文件,而是文件夹,那么请在 git rm --cached 命令后面添加 -r 命令,表示递归的删除(子)文件夹和文件夹下的文件,类似于 rm -rf 命令。

    如果你要删除的文件很多, 可以写进一个.sh文件批量执行, 如果文件或路径里有中文, 由于MinGW或CygWin对中文路径设置比较麻烦, 你可以使用通配符*号, 例如: sound/music_*.mp3, 这样就把sound目录下以music_开头的mp3文件都删除了.

    例如:新建一个 bash 脚本文件,del-music-mp3.sh:

    #!/bin/bash
    
    git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch projects/Moon.mp3' --prune-empty --tag-name-filter cat -- --all
    git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch sound/Music_*.mp3' --prune-empty --tag-name-filter cat -- --all

    如果你看到类似下面这样的, 就说明删除成功了:

    Rewrite 48dc599c80e20527ed902928085e7861e6b3cbe6 (266/266)
    # Ref 'refs/heads/master' was rewritten

    如果显示 xxxxx unchanged, 说明repo里没有找到该文件, 请检查路径和文件名是否正确.

实际例子操作如图:

添加到.gitignore文件里并push修改后的repo

如果想以后也不会再上传这个文件或文件夹, 请把这个文件或文件夹添加到.gitignore文件里, 然后再push你的repo.

添加到.gitignore文件:

$ echo "YOUR-FILE-WITH-SENSITIVE-DATA" >> .gitignore
$ git add .gitignore
$ git commit -m "Add YOUR-FILE-WITH-SENSITIVE-DATA to .gitignore"
[master 051452f] Add YOUR-FILE-WITH-SENSITIVE-DATA to .gitignore
1 files changed, 1 insertions(+), 0 deletions(-)

再次检查是否已经从存储库的历史记录中删除了所有想要删除的内容,以及是否检出了所有分支。

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

git push origin --force --all
Counting objects: 1074, done.
Delta compression using 2 threads.
Compressing objects: 100% (677/677), done.
Writing objects: 100% (1058/1058), 148.85 KiB, done.
Total 1058 (delta 590), reused 602 (delta 378)
To https://github.com/YOUR-USERNAME/YOUR-REPOSITORY.git
+ 48dc599...051452f master -> master (forced update)

这个过程其实是重新上传我们的repo, 比较耗时, 虽然跟删掉重新建一个repo有些类似, 但是好处是保留了原有的更新记录, 所以还是有些不同的. 如果你实在不在意这些更新记录, 也可以删掉重建, 两者也差不太多, 也许后者还更直观些。

为了能从打了 tag 的版本中也删除你所指定的文件或文件夹,您可以使用这样的命令来强制推送您的 Git tags:

$ git push origin master --force --tags

告诉您的协作者,从您的旧(受污染的)存储库历史中重新创建分支,而不是合并它们。一个合并提交可能会重新引入一些或所有您刚刚陷入清除麻烦的受污染的历史。

清理和回收空间

经过一段时间之后,您确信git filter-branch没有意外的副作用,您可以使用以下命令强制解除对本地存储库中的所有对象的引用和垃圾回收(GC)。

$ git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
$ git reflog expire --expire=now --all
$ git gc --prune=now
Counting objects: 2437, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (1378/1378), done.
Writing objects: 100% (2437/2437), done.
Total 2437 (delta 1461), reused 1802 (delta 1048)

您还可以通过将过滤后的历史推入一个新的或空的存储库,然后从GitHub创建一个新的克隆来实现这一点。

上面命令的第一句也可以换成:

$ rm -rf .git/refs/original/

参考自:

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

https://www.cnblogs.com/shines77/p/3460274.html

文:铁乐与猫

2018-11-17

【end】

Git永久删除文件和历史记录的更多相关文章

  1. Git如何永久删除文件(包括历史记录)

    有些时候不小心上传了一些敏感文件(例如密码), 或者不想上传的文件(没及时或忘了加到.gitignore里的), 而且上传的文件又特别大的时候, 这将导致别人clone你的代码或下载zip包的时候也必 ...

  2. 【Git的基本操作四】永久删除文件后找回

    永久删除文件后找回 1. 已经添加到本地库的文件 使用 reset 命令回退到未删除的历史记录即可 2.添加到缓存区,没有提交到本地库的文件找回 git reset --hard HEAD 命令即可找 ...

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

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

  4. git 批量删除文件夹和文件

    git 批量删除文件夹和文件 硬盘删除文件后,执行$ git status   会提示你仍然需要$ git rm <文件>   此时如果是要删除大批量文件,这么一个一个命令下去不得累死人啊 ...

  5. Git学习 -- 删除文件

    1 从版本库删除文件 git rm <file> git commit -m "xxx" 2 工作区中文件被误删,但版本库中没有删除,可以恢复到工作区 git chec ...

  6. git批量删除文件和批量提交

    1. 单个删除文件: ① 通常直接在文件管理器中把没用的文件删了,或者用rm命令删了:(可选操作,可直接执行②删除) $ rm test.txt ② 确实要从版本库中删除该文件,那就用命令git rm ...

  7. Git项目删除文件

    场景:项目中有一个文件test_exam_copy 文件之前提交上去的,现在不想要,本地也不要 方案一(手动图示删除): 直接登录到gitLab上面,进入该文件详情,直接删除,然后本机push下,则库 ...

  8. git 命令删除文件操作

    在github上只能删除仓库,却无法删除文件夹或文件, 所以只能通过命令来解决 1.添加文件并提交命令 2.推送到git服务器命令 3.删除文件并提交命令 4.推送到git服务器 查看下git 是否存 ...

  9. 『现学现忘』Git基础 — 35、Git中删除文件

    目录 1.删除文件说明 2.删除文件操作 (1)仅删除暂存区的文件 (2)完全删除文件 3.本文用到的命令总结 1.删除文件说明 在Git工作目录中要删除某个文件,首先要清楚该文件所处的状态. 若要是 ...

随机推荐

  1. 微信小程序treeview

    这是昨晚加班的时候,用微信小程序写的一个treeview组件. 先来看看效果图吧! 比较简单吧,直接view布局. 移动端实现treeview类似的效果,有大的局限性.首先受设备宽度的影响,如果像PC ...

  2. Android 系统内核层与 Linux Kernel 的比较

    Android 内核具有和标准 Linux 内核一样的功能,主要实现了内存管理.进程调度.进程间通信等功能.但在文件系统.进程间通信.内存管理等方面存在差异. 1.文件系统.移动设备采用的大多不是硬盘 ...

  3. hashCode()方法和equal()方法的区别

    本文参考地址:http://www.cnblogs.com/zgq0/p/9000801.html hashCode()方法和equal()方法的作用其实一样,在Java里都是用来对比两个对象是否相等 ...

  4. 1-监控界面sql保存

    1, BufferSize_machine 1), template 主要用来监控buffersize的状态的 name: 模块名字, 用于后续调取使用, label: 模块显示名字, 在页面显示的 ...

  5. postgresql 清空数据表 truncate

    在 mysql 中如果需要清空表,只需要 TRUNCATE table_name; 即可,如果有自增的 id 字段,也会还原回 1, 但是 postgresql 与 mysql 稍有不同,postgr ...

  6. python argparse(参数解析模块)

    这是一个参数解析,可以用它快捷的为你的程序生成参数相关功能 import argparse(导入程序参数模块) # 创建argparse对象,并将产品简要说明加入show = '程序说明' ===&g ...

  7. sqlite+ef+powertools

    1,安装驱动以便支持VS2010/VS2012设计时 VS2010, http://system.data.sqlite.org/downloads/1.0.88.0/sqlite-netFx40-s ...

  8. Socket 类

    构造函数       名称 说明 Socket(AddressFamily, SocketType, ProtocolType) 新实例初始化 Socket 类使用指定的地址族. 套接字类型和协议. ...

  9. blfs(systemv版本)学习笔记-总页

    我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! lfs(systemv版本)学习笔记:https://www.cnblogs.com/renren-study-notes/p/ ...

  10. redis 集群搭建

    1.redis 集群 redis集群是一个无中心的分布式redis存储架构,可以在多个节点之间进行数据共享,解决了redis高可用.可扩展等问题,redis集群提供了以下两个好处 1.将数据自动切分( ...