本篇重點
- git revert的用途以及使用情境
- 還原指定或多個提交的方法
- 調整容易混淆的還原範圍寫法
- 多個還原合併成一次提交
- git revert和- git reset的差異
使用 Git 做版本控制,偶爾會遇到需要「還原某些修改」的情境,這時候除了常聽到的 git reset,還有一個更安全、常被忽略的指令:git revert。
git revert
用途
建立一個新的 commit,將指定 commit 的變更「還原」回去,換句話說,它不會直接刪除歷史紀錄,而是新增一個「還原某次修改」的提交。
使用情境
- 誤把有問題的功能合併進主要分支,需要「還原」但不能破壞歷史。
- 在多人協作的專案裡,避免因為 git reset改寫歷史而造成衝突。
還原指定提交
| 1 | git revert <commit-hash> | 
範例:
| 1 | git log --oneline | 
發現登入驗證功能 (b71c5a2) 有 bug,需要先移除功能
| 1 | git revert b71c5a2 | 
Git 會自動進入編輯器,讓你修改 commit message,通常預設會像這樣:
| 1 | Revert "新增登入驗證功能" | 
儲存後就會新增一個還原修改的提交了
| 1 | git log --oneline | 
還原多個提交
還原連續提交
容易混淆的還原範圍
| 1 | git revert <oldest-commit>..<latest-commit> | 
從 <oldest-commit> 的下一個提交開始到 <latest-commit> 為止,並依序產生「反向 commit」,<oldest-commit> 本身的內容並不會被還原。
範例
| 1 | git log --oneline | 
如果執行 git revert a84f0d1..c3d9e28,實際被還原的會是 b71c5a2 和 c3d9e28,而 a84f0d1 並不會被包含在內。
調整還原範圍的寫法
因為 <oldest-commit>..<latest-commit> 的範圍並不包含 <oldest-commit>,在實際使用時可能會造成混淆。
如果希望範圍正好是從 <oldest-commit> 到 <latest-commit>(包含 <oldest-commit> 本身),就需要在 <oldest-commit> 後面加上 ^,代表「從這個提交的前一個開始」。
| 1 | git revert <oldest-commit>^..<latest-commit> | 
範例
| 1 | git log --oneline | 
如果執行 git revert a84f0d1^..c3d9e28,實際被還原的就是 a84f0d1 到 c3d9e28。
多個還原合併成一次提交
還原多個提交會逐一產生「反向 commit」,如果不希望產生多個 commit,而是想把所有變更合併到一次提交中,可以使用 --no-commit 參數,然後再手動下 git commit
| 1 | git revert --no-commit <oldest-commit>^..<latest-commit> | 
範例
| 1 | git log --oneline | 
| 1 | git revert --no-commit a84f0d1^..c3d9e28 | 
還原非連續提交
如果要還原的提交非連續,無法使用範圍操作
| 1 | git revert --no-commit <commit1> <commit2> <commit3> | 
範例
| 1 | git log --oneline | 
| 1 | git revert --no-commit a84f0d1 b71c5a2 | 
git revert 和 git reset 的差異
| 指令 | 行為 | 是否保留歷史 | 適合場合 | 
|---|---|---|---|
| git revert | 新增一個「撤銷指定 commit」的提交 | 保留歷史 | 公開分支、多人協作 | 
| git reset | 將分支指標移動到指定 commit | 改寫歷史 | 私人分支、尚未 push 的情況 | 
範例
git revert
| 1 | A - B - C - D (main) | 
假設要還原 C,git revert C 後會變成:
| 1 | A - B - C - D - E (main) | 
E 這個新 commit 就是「還原 C 的內容」
git reset
| 1 | A - B - C - D (main) | 
執行 git reset B
| 1 | A - B (main) | 
原本的 C 和 D 會直接消失(歷史被改寫)
結論
| 語法 | 作用 | 
|---|---|
| git revert --no-commit A..D | 還原 B、C、D(不包含 A) | 
| git revert --no-commit A^..D | 還原 A、B、C、D | 
| git revert --no-commit A B C D | 手動指定還原 A, B, C, D | 
- git revert適合在多人協作、公開分支上使用,能保留完整歷史並安全還原修改。
- 如果要還原多個提交,可以 一次指定多個 commit 或 使用範圍語法。
- git revert和- git reset最大的差異在於是否「改寫歷史」:- revert會新增 commit,保留歷史。
- reset則會刪掉歷史,不適合公開分支。
 



