已推送到共用分支的修改出錯,想撤回時,先找到造成問題的那筆提交。Git revert會留下原提交,再新增一筆反向修改,適合需要保留共享紀錄的情況。下面用主視覺與頁尾兩個檔案說明:撤回錯誤主視覺,保留後來補上的聯絡資訊。
先確認要撤回的是哪個提交
網站首頁改了主視覺,提交也推送到共用分支後,才發現按鈕連到錯誤頁面。這時同事可能已經拉取你的修改,後面也可能多了其他提交。若目的是撤回這一次修改,Git的revert會新增一個反向修改的提交,原本的提交仍留在紀錄裡。讀者能看見哪次改錯、哪次撤回,之後也可以照正常流程推送修正。
先打開所在儲存庫,確認目前分支和工作目錄。這裡的例子只處理一般提交,不處理merge commit。尚未提交的內容要先另存或完成自己的提交安排;不要為了讓指令能跑,直接刪掉手上的修改。看見不認識的檔案或變更,先查清楚來源。
git status
git log --oneline -8
看差異,再複製目標的提交代碼
不要只按「上一個提交」的位置猜。假設修改主視覺後又有人補了頁尾聯絡資訊,目前的HEAD已經指向頁尾提交。此時執行git revert HEAD,撤回的會是頁尾,不是主視覺。用log找到主視覺那一筆,再用show讀清楚它動了哪些檔案與哪些行。
下方以BAD_COMMIT表示那筆錯誤提交的實際代碼。請把它換成自己從log查到的代碼,不能原樣複製成為一個檔名或分支名稱。若show顯示的不只是你想撤回的主視覺,也包括需要保留的功能,整筆revert就會一併反向處理那些修改。這時應先討論修正範圍,或寫一個精準的新修正提交,不要先撤回再碰運氣。
git show --stat BAD_COMMIT
git show BAD_COMMIT
用revert新增一筆撤回紀錄
目標確認好、工作目錄乾淨,再執行下面指令。–no-edit表示直接採用Git準備的提交訊息,不打開編輯器;它不表示略過衝突檢查,也不表示修改已經推送。成功後會新增一個提交,通常訊息會指出它撤回哪筆紀錄。
這個例子原先有三筆提交:初始主視覺、錯誤主視覺、頁尾聯絡資訊。撤回第二筆後,紀錄變成四筆;home.txt回到banner=old,而footer.txt仍是contact=ready。這說明反向修改可以保留後續不相干的檔案內容。但如果後續提交碰了同一段文字,結果可能需要處理衝突,不能把這個簡單例子的成功套到所有網站。
git revert --no-edit BAD_COMMIT
git log --oneline -4
git status
檔案回來後,還要確認網站行為
提交建立後,用show看這筆撤回究竟改了什麼,也可以比較撤回前後的差異。範例中只有主視覺檔案應該變動;頁尾聯絡資訊不應消失。若你實際修改的是模板、樣式或路由,要再跑專案的檢查,並在測試站打開涉及的頁面。
Git檔案內容回復,不等於訪客已經看到正確網頁。靜態網站可能需要重新建置,正式站可能要按既有流程部署;CDN或瀏覽器快取也可能仍提供舊資源。先確認程式與頁面結果,再依團隊正常流程推送並部署。不要把git push成功當成正式網站已更新的證明。資料庫或外部服務的動作也不會因為revert自動撤回。
git show --stat HEAD
git diff HEAD~1 HEAD -- home.txt
git status
遇到衝突時,先決定要保留的內容
如果Git報出衝突,先看status列出的檔案,再打開它們,依網站現在應有的內容處理衝突標記。完成後把修好的檔案加入暫存區,執行revert –continue;若你決定放棄這次撤回,使用revert –abort回到撤回開始前的狀態。
不要只保留某一邊,就假設那一邊永遠正確。反向修改與目前檔案可能同時涉及既有功能,需要看清楚每段用途。這篇的案例刻意讓主視覺與頁尾分屬不同檔案,所以沒有衝突;真專案遇到衝突時,應由理解那段程式的維護者核對。完成continue之後,一樣要重新讀差異和測試頁面。
git status
# 修正衝突後,換成實際檔案路徑
git add path/to/file
git revert --continue
# 決定放棄時才使用
git revert --abort
共享紀錄保留,不代表所有風險都撤除了
revert的用途是用新提交反向處理舊修改。若錯誤提交已經放進密碼、金鑰或個人資料,新增撤回提交後,舊內容仍可能從歷史讀到;必須另行處理憑證停用、資料外洩與歷史清理。單靠revert不能完成這件事。
同樣地,若錯誤程式已經寄信、寫入正式資料庫或呼叫付款服務,程式碼撤回也不會逆轉那些外部動作。維護者需要另外確認已產生的資料和交易,依自己的復原流程處理。這也是先看目標提交、確認影響,再決定修正方式的原因。
若之後發現這次撤回本身也不該保留,可以評估撤回那筆revert提交,但仍要先檢查目前檔案與後續修改。不要連續執行多次revert,只為了讓畫面暫時看起來正常。保留清楚的提交訊息與測試結果,會讓其他維護者更容易接手。
常見問題
只想撤回還沒提交的檔案,也用revert嗎?不用。revert的目標是已存在的提交;未提交檔案要先辨識工作目錄與暫存區的內容,再選適合的處理方法。本文不提供直接丟棄修改的指令,避免把不同狀態混在一起。
可以直接撤回merge commit嗎?merge有多個父提交,需要決定mainline,且撤回merge會影響之後合併的行為。不要照一般提交的例子自行加上-m 1;請先核對分支關係與Git官方說明,再由熟悉合併歷史的維護者處理。
revert之後一定能推送嗎?不一定。分支保護、其他人的新提交、權限及團隊審查流程都可能影響推送。先完成本地核對,再按共用分支的規則提交修正;本例沒有連接遠端,也沒有替你的網站做推送或部署。
交給其他維護者時,把錯誤提交、撤回提交與受影響頁面一起寫清楚。主視覺範例可以記錄按鈕目前指向哪個頁面、頁尾聯絡資訊是否保留,以及哪個版本已進入部署流程。若程式修改已核對,但正式站還沒更新,就把部署狀態另外記下。讓接手的人能查到具體檔案與提交,比只寫「已回滾」更容易判斷網站還需要做什麼。

評論0