【GIT技巧】清除歷史記錄中的敏感信息

背景介紹

在使用GitHub的過程中,假如某次提交代碼時不小心將密碼或SSH-key提交進了公共倉庫。當然,希望這種事情永遠也不會發生,但是如果真遇到了,該怎麼辦呢?

如果發現得及時,本地提交後還沒有推送到GitHub遠程倉庫的話,這種情況還好處理,直接修改代碼後通過git commit --amend即可。

但如果發現時已經推送到了GitHub遠程倉庫,或者已過了許久,後續有了很多新的commits,這種情況就會比較複雜了。

錯誤的方式是,直接在當前代碼中去除敏感信息,然後再提交到代碼倉庫中。這樣的做法只能在最新的代碼中去除了敏感信息,在git歷史記錄中仍然保存著敏感信息。

當然,也可以選擇直接將整個倉庫刪除了。不過,看著昔日精心提交的代碼記錄,實在是難以下手。

要是可以只刪除敏感信息部分,而不影響到其它提交記錄就好了。事實上,GIT的確支持這種操作。

處理方式

實現的方式有兩種,一是通過git filter-branch命令,另一種是採用一款開源的工具,BFG Repo-Cleaner。前者是GIT官方的實現方法,後者是一款採用Scala編寫的工具,號稱比git filter-branch更簡單、更快捷。

git filter-branch

先來看下git filter-branch這種方式。假設要在所有歷史提交記錄中刪除文件PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA,那麼就可以採用如下命令:

$ 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

> Rewrite 48dc599c80e20527ed902928085e7861e6b3cbe6 (266/266)

> Ref refs/heads/master was rewritten

正常情況下,通過執行上面的命令,就可以在所有歷史提交記錄中徹底刪除指定文件。如果要進一步確定的話,可以在.git目錄中進行全局搜索,確保已徹底清理乾淨。

然後,就可以通過如下命令將本地代碼推送到GitHub上,並強制覆蓋掉所有歷史記錄。

$ git push origin --force --all

可以看出,採用git filter-branch的操作命令十分複雜(複雜到我也不想理會每個參數的具體含義),這還只是選擇粗暴地將整個文件進行刪除的情況。如果不想刪除文件,而是單獨修改特定文件特定內容的話,操作會更加複雜,如有興趣可查看git官方文檔。

BFG Repo-Cleaner

估計也是因為官方的git filter-branch太過複雜,於是Roberto Tyley開發了BFG Repo-Cleaner這款工具。該工具是專門針對移除歷史記錄的需求而產生的,這可以從其簡介中看出來。

Removes large or troublesome blobs like git-filter-branch does, but faster. And written in Scala

使用BFG Repo-Cleaner之前,需要先下載BFGs jar(requires Java 7 or above)。

如果想實現前面例子中同樣的功能,刪除文件PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA,可以通過如下命令實現:

$ java -jar bfg.jar --delete-files PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA my-repo.git

如果不想刪除文件,而是單獨修改特定文件特定內容的話,就可以通過如下命令實現:

$ java -jar bfg.jar --replace-text replacements.txt my-repo.git

在replacements.txt文件中,應包含所有需要替換的內容,格式如下(不包含注釋內容):

PASSWORD1 # Replace with ***REMOVED*** (default)

PASSWORD2==>examplePass # replace with examplePass instead

PASSWORD3==> # replace with the empty string

regex:password=w+==>password= # Replace, using a regex

regex:r(n)==>$1 # Replace Windows newlines with Unix newlines

通過執行上述命令,BFG Repo-Cleaner就會掃描代碼倉庫的所有歷史提交記錄,並按照replacements.txt文件中的映射進行替換操作。

通過對比可以看到,BFG Repo-Cleaner的確是更加簡潔,這也是GitHub官方推薦的方式。不過,在BFG Repo-Cleaner的介紹文檔中也說了,該工具的優勢在於簡單和快捷,從功能強大的角度來講,它是比不上git-filter-branch的,有些操作也只能通過git-filter-branch完成。

如需了解BFG Repo-Cleaner的更多用法,可詳細閱讀其文檔。

寫在末尾

不要問我為啥寫了這麼一篇博客,讓我再哭一會兒。我也真心地希望大家永遠不會用到這些工具。

小心駛得萬年船,共勉!

閱讀更多

  • BFG Repo-Cleaner

  • Git - git-filter-branch Documentation

  • Removing sensitive data from a repository

  • Chapter 5. Lessons of History

歡迎關注我的博客和微信公眾號 DebugTalk

DebugTalk


推薦閱讀:

gitlab 與walle配合搭建,無法檢測,請教一下這個是什麼原因?
如何高效地使用 Git
Git的初步使用教程
高大上的Git

TAG:Git | GitHub | 网络安全 |