《Git 起來!》系列來到了最後十天,讓我們開始逐漸深入瞭解 Git 的進階功能吧!
在專案開發中,難免會出現「啊,我剛剛那個 commit 好像做錯了」的情況。
這時候,很多人第一個想到的就是 git reset
,但是 —— reset 會改變歷史
一旦你已經推到遠端,團隊其他人會瞬間崩潰 😱。
所以 Git 準備了一個更安全的工具:git revert
。
它的概念是:
與其假裝錯誤沒發生,不如大方承認,並且用一個新的 commit 來修正。
它就是你的 安全後悔藥:撤回 commit 的內容,但保留歷史完整,團隊合作更安心。
git revert
?簡單來說:
git revert <commit>
= 新增一個「反向 commit」,把指定 commit 的修改抵銷
特點:
比喻:
你的 commit 是日記上的一行,如果寫錯了,revert 就是在旁邊寫一行「改正註解」,而不是直接撕掉原本的日記。
假設歷史是這樣:
A --- B --- C --- D (main)
你發現 commit C
有錯,需要撤回。
git reset --hard B
結果:
A --- B (main)
C
和 D
都消失了(被 reset 抹掉)C
已經 push 遠端,會造成團隊困擾git revert C
結果:
A --- B --- C --- D --- C' (main)
C'
就是自動產生的反向提交,把 C
的改動抵銷如果壞掉的不只一個,可以指定範圍:
git revert A..C
這樣會反向的依序還原 B、C 的變更(注意:範圍 A..C
是「不含 A 本身,直到 C」)。
結果:
A --- B --- C --- D --- C' --- B' (main)
C'
、 B'
是用來抵銷 C
、 B
的新 commit(先 C'
、再 B'
)如果連 A
也一併 revert,就要用:
git revert A^..C
# 或
git revert A~..C
A^
& A~
:表示 A
的前一個 commit,這樣範圍就會覆蓋到 A
假設我們有一個錯誤的提交:
git log --oneline
abc123 修錯的功能
def456 新增登入頁面
...
我們想要「撤銷」abc123
,就可以執行:
# 撤回單一 commit
git revert <commit-hash>
# 範例
git revert abc123
執行後會進入編輯 commit 訊息畫面,預設訊息通常是:
Revert "原本 commit 訊息"
可以保留或修改訊息,然後儲存退出即可。
這時候 Git 會幫你建立一個「新的 commit」,內容是「把 abc123
做的修改反向操作」。
換句話說,它不會抹掉歷史,而是新增一個 commit 來打臉錯誤。
有時候你會一次做了幾個連環錯誤 commit ,也可以用範圍一次還原:
git revert <old_commit>..<new_commit>
# 連續撤回最近三個 commit
git revert HEAD~2..HEAD
# 撤回指定的 commit-hash 範圍
git revert abc123..def456
abc123
之後到 def456
的提交全部反向操作⚠️ 注意:這會逐一產生多個 revert commit,而非一次性覆蓋。若 commit 很多,建議分批操作
確認本地分支最新:
git pull
使用 git revert
產生反向 commit
推送到遠端:
git push origin main
同事拉取後,修改就會被「安全撤回」。
有時候 revert 也會遇到衝突,這時候流程和解決 merge 衝突很像,必須手動解決衝突並重新提交。
解決流程如下:
git revert <commit_hash>
# 發生衝突
# 解決檔案衝突後
git add .
git revert --continue
小提醒:如果在執行過程中遇到衝突,git revert 會中止並要求你解決衝突,解決完要用 git revert --continue(或用 --skip 跳過、--abort 取消)。
撤回 merge commit:需要加 m 1
指定父分支
git revert -m 1 <merge-commit-hash>
配合 branch:如果不確定,先在 feature branch 試 revert,再 merge 回 main
如果只想暫時看看結果,可以加 -no-commit
:
git revert <commit-hash> --no-commit
這樣改動會套用到工作目錄,但不會立刻生成 commit,讓你可以先檢查。
在團隊合作中,建議盡量用 git revert
取代 git reset
,避免搞亂大家的歷史紀錄。
指令 | 特性 | 適用情境 |
---|---|---|
git reset |
回到指定版本,刪除之後的歷史 | 個人開發、尚未分享給他人 |
git revert |
產生一個新提交,抵銷指定版本的修改 | 團隊協作、需要保留歷史 |
git reset
:把專案狀態倒回去,好像把時間線硬生生抹掉。git revert
:在現有歷史的基礎上,再新增一個「反向 commit」,抵銷之前的修改。
簡單來說:
👉 reset = 假裝沒發生(會改歷史)
👉 revert = 承認錯了,但加註說明(不改歷史)
git log --oneline
,找出一個錯誤 commitgit revert <commit-hash>
撤回修改git revert
會新增一個「反向 commit」,安全還原錯誤變更。git reset
那樣直接改寫歷史,因此非常適合團隊協作。想像每日 commit 是日記,revert 就是在旁邊貼上一行「更正註解」
不撕掉原本日記,團隊也看得懂。