我們常用的 git rm
僅對 Working Tree 構成影響,如果想永久的刪除倉庫中的文件或目錄,那么就要用到 git filter-branch
命令了。git filter-branch
會檢索整個 Commit 歷史,逐一改寫 Commit Object,重構整個 Tree。
git filter-branch --tree-filter 'rm -rf path/folder' HEAD
git filter-branch --tree-filter 'rm -f path/file' HEAD
也可以指定 檢索的 Commit 歷史的范圍:
git filter-branch --tree-filter 'rm -rf path/folder' 347ae59..HEAD
最后,不要忘了向倉庫強制推送所有的變化:
git push origin master --force
執行 git filter-branch
命令后,已經標記為刪除的 Object 在本地倉庫中要到過期后才會解除關聯和進行垃圾回收。檢查哪些 tags 和 branch 引用了這些 Object:
git for-each-ref --format='delete %(refname)' refs/original
如果想立即解除關聯,執行垃圾回收,可以這么做:
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now
接下來,就是強制推送到倉庫了:
git push origin --force --all
git push origin --force --tags
不到迫不得已,不要輕易使用 git filter-branch
,因為它重構了整個 Tree,所以每個開發人員都需要重新克隆倉庫到本地,對于有很多開發者參與的大型項目來說,這么做會給很多人帶來麻煩,與其事后對倉庫內容進行修正,不如伊始就對每個 Commit 慎之又慎。