← 上一章:【狀況題】手邊的工作做到一半,臨時要切換到別的任務 下一章:【狀況題】如果你只想要某個分支的某幾個 Commit? →


【狀況題】不小心把帳號密碼放在 Git 裡了,想把它刪掉…

你不小心把帳號密碼寫在某次的 Commit 裡,而且已經 Push 出去了…

如果已經 Push 出去,請不要先想要怎麼用 Git 來解決,請先直接改密碼再說!

改完密碼了嗎?那接下來我們再來看看怎麼解決這件事吧。

砍掉重練大法

這招是屬於「逃避雖然可恥但是有用」的做法,把因為所有的 Commit 紀錄都在 .git 目錄裡,所以可以這樣:

  1. 把 .git 目錄刪掉。
  2. 把那個密碼檔刪掉或修掉。
  3. 重新 Commit。

不要以為我是在開玩笑,這也是一招,而且是比較不需要什麼技術的招式,缺點就是之前的 Commit 紀錄都不見了。所以這個專案如果只有你自己一個人做,而且也不在乎之前的 Commit 紀錄的話,這也是一個選擇。

使用 filter-branch 指令

如果你不想使用砍掉重練大法,另一個選項就是使用 Git 的 filter-branch 指令。假設目前的 Commit 紀錄是這樣:

current commit

在這個例子裡,我從第二個 Commit(382a2a5)開始就已經把資料庫的密碼加進去了。

假設我想要把 config/database.yml 這個檔案從每個 Commit 裡把它拿掉,比較直覺但稍微比較辛苦的做法是使用 Rebase 指令,然後一個一個 Commit 去編輯。Git 有一個叫做 filter-branch 的指令,這個指令不算太常見,但它可以一次大量的修改 Commit。

$ git filter-branch --tree-filter "rm -f config/database.yml"
Rewrite db3bbec63301d1c638e828c9a38a29314c8a0c44 (9/10) (1 seconds passed, remaining 0 predicted)
Ref 'refs/heads/master' was rewritten

說明:

  1. filter-branch 這個指令可以讓你根據不同的 filter,一個一個 Commit 的來處理它。
  2. 這裡使用了 --tree-filter 這個 filter,它可以讓你在 Checkout 到每個 Commit 的時候執行你指定的指令,執行完後再自動幫你重新再 Commit。以上面這個例子來說,便是執行「強制刪除 config/database.yml 檔案」這個指令。
  3. 因為刪除了某個檔案,所以在那之後的 Commit 全部都會重新計算,也就是說等於產生一份新的歷史紀錄了。

東西一旦加到 Git 裡,真的要把它刪掉其實沒那麼容易,我們在下一章「【冷知識】怎麼樣把檔案真正的從 Git 裡移掉?」章節會再做更多的說明。

啊!我又後悔了,怎麼回復剛剛 filter-branch 造成的結果?

使用 Git 的好處,就是後悔隨時可以重來。其實在進行 filter-branch 指令的時候,Git 會幫你把之前的狀態備份一份在 .git/refs/original/refs/heads 這個目錄裡(其實說是備份,也只是備份開始進行 filter-branch 之前的那個 HEAD 的 SHA-1 值而已)。所以你可以從這個檔案把 SHA-1 值找出來然後再 hard Reset 回去,或是直接這樣也可以:

$ git reset refs/original/refs/heads/master --hard
HEAD is now at db3bbec add fish

這樣就都回來了。

如果已經推出去了…

老實說,推出去的東西就跟潑出去的水一樣收不回來,你能做的就是使用 git push -f 指令,重新強制推一份你剛剛 filter-branch 過的 Commit 上去。在「Push 上傳到 GitHub」章節會有更多關於 Push 相關的介紹。


← 上一章:【狀況題】手邊的工作做到一半,臨時要切換到別的任務 下一章:【狀況題】如果你只想要某個分支的某幾個 Commit? →

Comments