Day26|【Git】 从 Git 中移除重要个资或彻底清除档案 - git filter-branch

有时候当我们在写程序码时会用到一些 API 金钥,或是个人的帐号、密码,这些都是属於「敏感资讯」,一旦不小心 Push 出去,可能会受到有心人士的利用。所以当不小心把重要个资、机密文件传出去时,请先改密码改密码改密码!後续再来找解决办法,这样才是保护资料的首要之责。


改完密码、确保密码重设之後,接下来可以思考如何从 Git 中将这些资料给移除。

最直接、直觉、也最快的方式 - 直接砍掉重练

将档案 Push 之前都会先经过 Commit 将档案提交到储存库,而这些纪录都是被存在 .git 目录之中。

因此我们可以对 .git 进行动作,将 Commit 的资料都给删除。

执行步骤

  1. 将 .git 目录删除 → 如此一来档案就不再被 Git 掌控了!

    https://ithelp.ithome.com.tw/upload/images/20211009/20141010kh1iN1ZPUt.png

  2. 将原先有保留重要机密资料或帐号密码的档案删除/修改。

  3. 重新再 Commit 一次新的版本。(重新进行版本控制流程)

    $ git init # 进行版本控制(此时就会有 .git 目录产生)
    $ git add . # 将档案加至暂存区
    $ git commit -m"纪录讯息" # 提交档案至储存库
    

⚠️要注意的是:

一但将 .git 目录移除时,同时也代表之前所有的 Commit 纪录也一并删除

也许这样并不是最好的办法,但它是其中一个选择。

假设今天只是单纯是你个人的练习、本地端的操作,或是专案只有你一人负责,那麽不妨可以参考这个做法。


上面的方法提到会将整个 .git 目录删除,同时代表整个 Commit 纪录也会被删除。

但是今天如果你是团队分工,这份专案的 .git 是不能够随便删除的,或者已经被 Push 出去到远端,那麽方法一就不太适合,这时候可以考虑接下来的做法。

步骤一|使用 filter-branch 指令

filter-branch - 可以一次修改大量 Commit

$ git filter-branch --tree-filter "rm -f 档案名称"

🛠实际操作

  • filter-branch 指令

    状况|假设今天我是将「敏感资讯」存在 insex.html 内,但我将它 Commit 出去,我想把有关於 insex.html 的 Commit 纪录移除掉。

    目前 git_practice 目录下有的档案:

    https://ithelp.ithome.com.tw/upload/images/20211009/20141010PQHQvDBmdC.png

    执行指令来移除 Commit:

    $ git filter-branch --tree-filter "rm -f insex.html"
    

    https://ithelp.ithome.com.tw/upload/images/20211009/201410108Sy6yUwtJR.png

    得到的回馈讯息:
    Rewrite 0e915cf76c1822389d8ab862fe0e70d1faeed313 (4/4) (0 seconds passed, remaining 0 predicted)
    Ref 'refs/heads/one' was rewritten

    回到 git_practice 目录可以看到 insex.html 档案不见了。

    https://ithelp.ithome.com.tw/upload/images/20211009/20141010W207HM9hCZ.png

    如此一来之前 Commit 纪录里若有 Iinsex.html 这个档案,都会一并被移除掉,不再 Commit 里。

👉 指令说明:

  1. filter-branch 可以根据不同的 filter ,逐一 Commit 处理它。
  2. --tree-filter 这个筛选参数,意思是可以让你在切换/检查Checkout)到每个 Commit 时执行指定的指令,执行完後再自动 Commit 新的版本
  3. 先前有提到过 Commit 的 SHA-1 校验码是有一定规则计算的,因此现在将其中一个档案删除後,计算结果将有所不同,则重新 Commit 後整个数值都改变了,相当於产生了一份新的历史纪录
  4. 在回馈讯息中可以看到 Ref 'refs/heads/one' was rewritten 这些讯息,这意思是 Git 将你之前的状态备份一份在 .git/refs/orignal/refs/heads/one 这个目录里,或是也可以说是备份开始进行 filter-branch 之前的 HEAD 的 SHA-1 值

https://ithelp.ithome.com.tw/upload/images/20211009/20141010DMIH186C8A.png

https://ithelp.ithome.com.tw/upload/images/20211009/20141010d9shNQZDgr.png

👉 透过第四点的说明可以了解到,我们拥有之前的 HEAD 的 SHA-1 值,所以当如果我们後悔刚才所执行的 filter-branch 指令时,可以使用以下指令来回复:

$ git reset refs/orignal/refs/heads/one --hard

如此一来就可以取消先前的动作罗!


如上述提到的,即使我们执行了指令, Git 还是会自动帮你备份,让你有办法救回。

所以进来 Git 容易,想要离开却很难啊!

那麽有没有什麽办法可以真正地将档案从 Git 中移除呢?

#将档案彻底从 Git 中移除

  1. 移除整个 .git 目录

    因为 Commit 纪录都在 .git 目录中,直接砍掉重练是最快的方式,但之後还需要重建一次。

  2. 使用 Rebase 或 filter-branch 指令整理

    • Rebase - 适用於只有少量的 Commit,可以直接进行编辑、重整。
    • filter-branch - 可以大范围对每个 Commit 执行某个指令,并於修改完後自动重新 Commit。

    先前执行 filter-branch 指令依然会保留备份的档案在其他处,因此我们可以加上 -f 参数,意指强制覆写 filter-branch 的备份点。

    👉加上 -f 参数:

    $ git filter-branch -f --tree-filter "rm -f 档案名称"
    

    执行 filter-branch 指令後,可以成功将档案移除掉,但是我们还有一些需要做的事情,才能将档案全部断乾净。

    👉移除备份点 - rm 指令

    $ rm refs/orignal/refs/heads/one
    

    👉Reflog

    $ git Reflog expire --all --expire=now  
    

    此指令是因为 Git 有个资源回收的机制,预设是要等 30 天才会整个移除档案。因此这里的指令是要要求 Reflog 立刻过期

    接着可以使用 git fsck 指令看到我们先前移除掉的档案,这些都变成 Unreachable 状态的档案。

    $ git fsck --unreachable  
    

    Unreachable 是指在 Commit 与分支中没有一个连结点可以到达的档案。

    得到 Unreachable 状态的档案後,启动资源回收机制,呼叫垃圾车来将档案载走,如此一来就成功地将档案完完全全地从 Git 中脱离控制啦!

    $ git gc --prune-now
    

    整理流程:

    1. 执行 filter-branch 强制覆写指令 git filter-branch -f --tree-filter "rm -f 档案名称"
    2. 移除备份点 rm refs/orignal/refs/heads/one
    3. Reflog 中的也移除并要求立马过期 git Reflog expire --all --expire=now
    4. 启动资源回收机制将垃圾载走 git gc --prune-now

<<:  【Day29】[演算法]-基数排序法Radix Sort

>>:  Day 26:53. Maximum Subarray (2)

Day 44. 之後..

前阵子因为升级作业系统到Big sur失败,导致直接重灌,而且是最严重的那种,资料救不回来的那种,懒...

Day#26 传送对话(1)

前言 前一天结束在点选某个搜寻到的使用者,今天接着做跟该使用者展开对话吧! New Conversa...

WP Rocket 一整年难得的7折优惠+7款外挂测速比较

黑色购物节,只有9天:所有方案7折 折扣内容:所有方案皆享「7折」优惠 折扣期间:2020/11/...

Day25-memo

前言 前面我们学习很多关於React生命周期、状态、取得DOM元素等等,今天我们要来改善React本...

DAY16: 实作浏览器采取想访问的HTML

今天会结合上一篇的DAY15:HTTP GET请求的观念,并且加入一些不一样的东西,除了Nodejs...