Git 還原特定檔案

前言:

Git 可以透過 Revert 還原某一次的修改,但是以 Commit 為單位去做復原的動作,假如這一次的 Commit 裡面包含了五個檔案的修改,而你只想要復原其中一個檔案,要怎麼做呢?

前情提要:

先依照下列步驟製造出一個類似的場景
$ touch abc.txt
$ git add abc.txt
$ git commit -m "Add abc.txt"
$ touch def.txt
$ git add def.txt
$ git commit -m "Add def.txt"
$ vim abc.txt    ==> 加入字串
$ vim def.txt     ==> 加入字串
$ git add .
$ git commit -m "Modify all files"

目前有三個 Commit,其中最新的一個 Commit 同時修改了 abc.txt. 和 def.txt。
 
假設現在我要還原稍早對於 def.txt 檔案的修改,可以怎麼做呢?我們先來看一個比較不好的操作方式,為什麼不好?稍後會做說明。
$ git reset HEAD~    ==> 復原至上一個 Commit
$ git checkout -- def.txt    ==> 取消 def.txt 的修改
$ git add .
$ git commit -m "Revert def.txt"

此時 def.txt 已經被還原為原本的樣子,而最新的 Commit 也只有修改 abc.txt,但是,此時的 Commit 歷史紀錄也已經不一樣了!如果在多人共同開發的情況之下,修改已經 Push 至遠端的歷史紀錄是不被允許的,因此需要特別強調,此方法只能用於本地端,在你還沒將舊的修改 Push 至遠端之前,才可以這麼做喔!

再來要說明的是我比較推薦的操作方式,此方法背後的原理就類似於新增一個新的 Commit,而這 Commit 的內容就是將先前的修改給復原回去,如果修改的內容只有一兩行,直接手動去修改也是沒有問題的,但既然 Git 有提供更方便簡潔的指令,何不嘗試看看呢!

Git Checkout:

$ git log --oneline def.txt    ==> 找到 def.txt 的上一個版本
$ git checkout <commit-id> def.txt    ==> Checkout 回某個版本
$ git diff --cached def.txt    ==> 確認修改內容
$ git commit -m "Revert def.txt"


此時已經單獨將 def.txt 還原成上一次的修改,我們來看看最新的歷史紀錄。

可以很清楚的發現,過去的 Commit 歷史紀錄仍然存在,唯獨增加了一個新的 Commit,這樣一來既不會影響過去的 Commit 也可以單獨還原特定的檔案。

參考資料:
[StackOverflow]Reverting a single file to a previous version in git

留言

這個網誌中的熱門文章

程式語言常用之符號與詞彙 - 中英文對照

Repo 實用指令

什麼是 Bootloader?