0

Git 實戰 - 將檔案從歷史 Commit 中移除

 8 months ago
source link: https://blog.darkthread.net/blog/rm-files-from-git-history/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Git 實戰 - 將檔案從歷史 Commit 中移除

2022-03-25 10:28 PM 1 4,088

程式版控不該發生,但難免會遇到的狀況 - 想移除歷史 Commit 裡不該被放進去的檔案,例如:無保存價值的大檔或是機密資料。

如果是無用大檔,即使將檔案刪除再 Commit,日後 clone 仍會佔用頻寬及儲存空間;而機密資料則是非清除不可。Git 允許我們修改歷史並 push -f 覆寫,但實務上會造成開發團隊夥伴的困擾,覆寫後版本會跟其他人先前取得的版本不一致,需要善後。(參考:Git Force Push 後如何更新 Repository by Yowko)

如果了解副作用,也有充分理由必須回到過去重寫歷史,同時也已取得夥伴諒解確認不會被蓋布袋,下面是兩個簡單練習,供未來的我及有需要的同學參考。

【情境一】

歷史有四次 Commit,想移除第二次 Commit 不小心放入的 WiFiPasswd.txt:

利用 git rebase -i 837658aa (Commit "init") Rebase 第二到四個 Commit,將 Poc Commit 標為 edit,要求在此停下修改:

存檔後,版本會停在 PoC Commit,顯示 "Stop at aacb399... Poc You can amend the commit now" 訊息,此時下指令 git rm WiFiPasswd.txt 移除檔案,再下指令 git commit --amend 修改 Commit。COMMIT_EDITMSG 檔可看到檔案清單的 WiFiPasswd.txt 已消失,只剩 Program.cs [1],此時亦可修改 Commit 訊息[2]:

之後執行 git rebase --continue,後面兩個 Commit 不需修改,Rebase 完成。再檢視 Poc Commit,其中已無 WiFiPasswd.txt:

【情境二】

有個 secrets 目錄存在多個 Commit,打算將整個資料夾從歷史抹去:

使用 filter-branch 指令,配合 index-filter --all 對所有 Commit Index 跑一次 git rm 將 secrets 目錄移除再重新 Commit。 (註:另一個做法是用 tree-filter 將 Commit 內容還原到暫存目錄修改,優點是可對實體檔案內容做精密調整,缺點是速度較慢,若為單純移除檔案,index-filter 較有效率)

git filter-branch --force --index-filter "git rm --cached --ignore-unmatch secrets -r" -- --all

由訊息可看到 secrets 的兩個檔案被從第二到第四個 Commit 移除。但要注意,刪除檔案在本機仍可被還原,要徹底清除可參考龍哥這篇 【冷知識】怎麼樣把檔案真正的從 Git 裡移掉?

註:官方推薦用 filter-repo 取代 filter-branch,效率較好且功能更多,但需額外下載安裝,先筆記,未來有需要再學。

以上是兩個從歷史抹去檔案的範例,希望大家不會用到它們。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK