1. 程式人生 > >Git 永久刪除檔案

Git 永久刪除檔案

簡略版

假設要刪除的檔案是password.txt,執行如下命令:

git filter-branch --force --index-filter 'git \
rm --cached --ignore-unmatch password.txt' \
--prune-empty --tag-name-filter cat -- --all

如果commit已經同步到了github,那麼再執行如下命令永久刪除遠端上的檔案。

git push --all --force

不用關心各條命令在幹什麼,大功告成!

詳細版

你如果有耐心或者有興趣知道上面兩條命令是如何工作的,就接著往下讀。。。

問題的產生

眾所周知,git是用來進行版本控制的,可以恢復到任何commit了的歷史狀態,對於新手來說,經常會把一些不必要的資料或者敏感資料放到github的公開專案中。比如說我,剛接觸git時,每次修改之後都用 git add .圖省事,結果一些.class, .zip, .exe檔案都被commit了,很煩人。要是不小心提交了密碼或者機器的SSH key,就容易產生安全隱患。

一個簡單但錯誤的辦法就是使用git rm password.txt 命令刪除敏感檔案,但是這僅僅是把檔案從當前版本中刪除,歷史版本中仍然有。

下面來說說正確命令的每個選項是什麼意思:

git filter
-branch --force --index-filter 'git \ rm --cached --ignore-unmatch password.txt' \ --prune-empty --tag-name-filter cat -- --all

filter-branch 是讓git重寫每一個分支,
--force 假如遇到衝突也讓git強制執行,
--index-filter 選項指定重寫的時候應該執行什麼命令,要執行的命令緊跟在它的後面,在這裡就是git rm --cached --ignore-unmatch password.txt ,讓git刪除掉快取的檔案,如果有匹配的話。

--prune-empty 選項告訴git,如果因為重寫導致某些commit變成了空(比如修改的檔案全部被刪除),那麼忽略掉這個commit。

--tag-name-filter 表示對每一個tag如何重新命名,重新命名的命令緊跟在後面,當前的tag名會從標註輸入送給後面的命令,用cat就表示保持tag名不變。
緊跟著的-- 表示分割符,最後的--all 表示對所有的檔案都考慮在內。

預防措施

今後為了防止再次不小心將敏感資料提交,可以修改.gitignore檔案的內容,凡是成功匹配的檔案都不會被git看到,比如在本例中可以在.gitignore後面追加一行”password.txt”

參考資料: