2022年8月19日 星期五

Git - 如何取消歷史 commit 中對某個檔案的修改紀錄

今天遇到一個情況是,
在 Git 的 commit 歷史紀錄中,
希望把其中有一次的 commit 中的某個檔案修改取消掉。
例如假設我現在狀態最新 commit 是 commit_0,
之後修改了檔案 file_1 和檔案 file_2 並 commit 成 commit_1,
接著又修改其他東西 commit 了 commit_2, commit_3 之類的,
但後來我反悔了,想把 commit_1 中對檔案 file_1 的修改取消掉,
也就是希望當作之前在 commit_1 中沒有修改過 file_1。

在這篇文章中特別紀錄一下上述情境的解法:
首先先列出一下 commit 的紀錄如下:

commit_3 ........
commit_2 ........
commit_1 修改了 file_1, file_2
commit_0 ........

首先要執行以下指令進入 git rebase interaction 互動模式

git rebase -i {commit_0 的 commit id}

接著會跳出編輯器供修改,例如可能是以下內容:

pick {commit_0 的 commitId} ......
pick {commit_1 的 commitId} ......
pick {commit_2 的 commitId} ......
pick {commit_3 的 commitId} ......

因為要修改的是 commit_1,所以我們要把 commit_1 的 "pick" 改成 "edit",
改完後儲存關掉,回到指令視窗,
執行以下指令將 file_1 的內容變回在 commit_1 之前,也就是在 commit_0 時的狀態:

git checkout {commit_0 的 commit id} -- {file_1 的路徑}

再來把已回復內容的 file_1 加進暫存區以進行 commit:

git add {file_1 的路徑}

接著再執行如下的 commit amend 指令,重新 commit 以取代原來的 commit_1 ,
這樣因為對於 commit_0 來說 file_1 在這次的 commit 其內容並沒有任何被修改的地方,
所以新的這個 commit_1 將不會有修改 file_1 的紀錄:

git commit --amend

最後我們再執行如下的 rebase continue 指令讓 rebase 的程序繼續進行下去至結束就行了。

git rebase --continue

參考資料:

  1. While editing a commit in `git rebase -i`, have to revert changes in a single file