前面我們談的是理想情況:您寫程式、建立 commit,再開啟 Pull Request。但實際工作中常會出狀況:忘了加入檔案、commit 訊息打錯字,或發現方向走偏了。本文會介紹如何用 IDE 工具處理幾種常見問題。

範例與介面截圖以 JetBrains IDE 為準;操作名稱和位置可能因您使用的版本而異。練習請使用獨立的教學用儲存庫。在工作專案中,請遵循該專案的分支、commit 與推送規範。

Claude Code 在專案中工作時,已保存的歷史記錄能幫您回到先前的狀態。但 Git 不會記錄每一次按鍵,尚未 commit 的修改可能會遺失。復原前,請確認分支、選取的檔案,以及您需要的副本是否存在。

Rollback - 還原本機變更

情境:您修改了檔案,後來發現這些修改都不對,想快速將檔案恢復到最近一次 commit 的狀態。

"Rollback - 還原本機變更"章節插圖

請使用 Rollback:

  1. 在左側面板開啟 Commit 分頁;
  2. 在清單中找到要還原的已變更檔案(也可以選取多個);
  3. 按右鍵並選擇 Rollback(或點選圓弧箭頭圖示)。

IDE 會提醒您,選取的本機變更將會遺失。先檢視 diff,並保存需要的內容。只有確定要丟棄這些修改時才確認 Rollback,接著檢查結果。這會刪除尚未 commit 的工作,不是替它備份。

請留意

執行 Rollback 前,先把代理的修改與同一檔案裡原有的變更區分開來。Rollback 會將選取的檔案還原到最近一次 commit(HEAD)的狀態,並丟棄已暫存和未暫存的修改。這和不帶旗標的 git restore 不同:後者從 index 取出內容,只會變更工作目錄中的檔案。

Amend - 補充最近一次 commit

情境:您剛按下 Commit,馬上就想到忘了加入重要檔案(例如更新過的測試),或是 commit 訊息有錯字。如果 commit 還沒推送,可以使用 Amend。另做一個修正用的 commit 也可以,歷史已經和其他人共用時尤其適合。

"Amend - 補充最近一次 commit"章節插圖

若要補充尚未推送的 commit,請使用 Amend(補充或修正):

  1. 在 Commit 視窗中修改遺漏的檔案,並勾選檔案旁的方框;
  2. 在 Commit Message 面板找到 Amend 核取方塊(或點齒輪圖示 -> Amend Commit),再勾選它;
  3. IDE 會帶入上一個 commit 的訊息,您可以修改內容;
  4. 按下 Commit。

Amend 會建立一個識別碼不同的新 commit,取代原本的 commit。舊物件不會直接被修改。如果先前的 commit 已推送,而且其他人也在使用,通常另做一個修正會更合適。

這項功能的詳細說明,請參閱 JetBrains 官方教學。

Undo Commit

情境:您建立了 commit,但還沒有透過 Push 推送,隨即發現自己太急了。您希望這個 commit 從歷史記錄中消失,修改本身則留在編輯器中,好繼續完成工作。

請使用 Undo Commit:

  1. 開啟歷史記錄,也就是底部的 Git -> Log 分頁;
  2. 找到目前分支(HEAD)的最近一次 commit,而不是直接選整張 commit 圖最上方那一列,並開啟它的快顯選單;
  3. 選擇 Undo Commit。
"Undo Commit"章節插圖

選擇變更清單(通常是 Default Changelist),然後按 OK。這個 commit 會從歷史記錄中消失,檔案則會以已修改狀態回到 Commit 視窗。您沒有遺失任何內容,可以放心繼續寫程式。

Reset - 移動分支與檔案狀態

Reset Current Branch to Here... 會將分支指標移到您選取的 commit,是個功能強大的工具。視情況而定,它可以溫和地撤銷最近的操作,也可能徹底清除有問題的程式碼。

情境 A - 撤銷最近的本機 commit

您在本機建立了幾個 commit(尚未 Push),後來發現這整段開發方向都錯了。

  1. 開啟 Git -> Log 分頁;
  2. 找到您想回到的最後一個正常 commit(也就是那串錯誤 commit 之前的那個);
  3. 按右鍵並選擇 Reset Current Branch to Here...。

情境 B - 重設為伺服器上的狀態

您想依據遠端分支還原受追蹤的檔案。先保存需要的本機工作,再執行 Fetch:origin/main 標記反映的是最近一次取得的狀態,不是伺服器持續更新的即時狀態。如果目前有衝突中的操作,先處理並完成或取消它;別把 Hard 當成萬用解法。

  1. 開啟 Git -> Log;
  2. 找到遠端分支標記,通常是帶有紫色 origin/main 標籤的 commit(或 origin/your_branch_name)。這是伺服器上最近一次已知的程式碼狀態;
  3. 在該 commit 上按右鍵,選擇 Reset Current Branch to Here...。
Reset Current Branch 視窗

Reset 模式

在重設視窗中,請審慎選擇模式。三種模式都會將目前分支移到選取的 commit,但對 index 和工作目錄檔案的處理方式不同:

  • Soft 保留工作目錄檔案和 index。Mixed 保留工作目錄檔案,但將 index 重設為選取的 commit,因此差異會維持未暫存狀態。這是兩種不同模式,不過兩者都能讓您繼續使用檔案內容工作;
  • Hard 會將 index 和受追蹤的檔案重設為選取的 commit,並清除其中尚未 commit 的修改。一般無關的 untracked 檔案可能會保留,但妨礙還原的路徑可能會被刪除。Commit 不會立刻從所有儲存區消失,但別指望之後還能救回工作。

Push 之後該怎麼做

情境:您執行了 push,之後才發現錯誤。

commit 一旦送到伺服器,就成為專案共用歷史的一部分。試圖改寫這段歷史(透過 Reset 或 Amend)可能會給同事帶來很大麻煩。想想看,他們可能已經拉取您的變更,並以此為基礎開始工作。

安全又合適的做法:建立一個新的 commit來修正錯誤,再照常執行 push。這是很常見的做法。錯誤程式碼後面緊接著一個清楚的修正 commit,這樣的線性歷史能讓整個團隊看懂專案如何演進。

IDE 也有專用的 Revert Commit 功能。在 Git -> Log 中對錯誤的 commit 按右鍵並選擇 Revert Commit,IDE 就會建立一個新的"反向 commit",執行與原 commit 相反的變更(例如移除新增的行)。

"Push 之後該怎麼做"章節插圖

Revert 適合用新的 commit 撤銷已推送的變更。程式碼和文字都能用這個方式處理,但可能與後續修改衝突。解決衝突後,請檢查最後的結果;如果修改彼此牽連,有時另外做一個修正會更清楚。

Stash / Shelve - 暫時收起變更

情境:您正忙著開發新功能,檔案清單裡紅藍標記一片。突然,team lead 跑來說:"先停一下,我們得馬上修正 main 分支上的 bug。"您無法切換到 main,因為目前有未完成而且互相衝突的變更。若專案規範允許,可以先建立本機中間 commit;如果現在不方便保存成 commit,也可以先把工作收起來。

做法是暫時把工作放進一個虛擬盒子。在 Git 裡這稱為 Stash,IDE 也有自己的機制 - Shelve(收到架上)。

  1. 開啟 Commit 視窗,選取已變更的檔案;
  2. 選擇 Shelve Changes...;這些步驟是 Shelve 的操作,Git Stash 要另外執行;
  3. 為這批收起的變更取個容易辨認的名稱,然後按 Shelve。
"Stash / Shelve - 暫時收起變更"章節插圖

執行 Shelve 後,請檢查剩下的檔案,確認需要的修改都已收起。現在可以切換到 main 修正問題,並依照專案規範保存結果。接著回到工作分支,開啟 Shelf 並選擇 Unshelve。

Git Stash 請使用獨立的 stash 清單,還原需要的項目。它是另一種儲存方式。一般 stash 不會包含新建立的 untracked 檔案,除非加上額外選項;切換分支前,確認需要的工作都有保存好。還原時可能發生衝突,完成後記得再次檢查檔案。

深入使用 Log

Git -> Log 視窗不只是 commit 清單,也是實用的調查工具。

  • Commit hash 是由字母和數字組成的字串,例如 a1b2c3d。它是每個程式碼快照的唯一識別碼。Log 中的 commit hash
  • 您可以依分支、作者、日期或 commit 訊息中的字詞篩選歷史記錄,快速找出誰在什麼時候處理了某個部分;
  • 若要找出新增或刪除特定程式碼行的 commit,可以在 Log 視窗中搜尋變更內容,不只限於 commit 訊息;
  • 在編輯器左側的邊欄(顯示行號的位置)按右鍵,選擇 Annotate with Git Blame。IDE 會在每一行旁顯示最後修改者及其 commit。接著開啟該 commit 和相關討論:Blame 只會指出某行最近一次由誰修改,不會說明原因。

高風險操作 - Force Push

我們已經知道,改寫推送出去的 commit 不是好主意。但如果您真的改了本機歷史(例如使用 Undo Commit 或 Amend),而伺服器上仍是舊版本呢?一般的 push 會失敗,因為 Git 會保護共用歷史,避免遭到覆寫。

Force push 允許您替換選定的遠端 ref,即使新歷史並非從舊歷史延續而來。它不會清空整台伺服器;影響範圍取決於您推送的 refs。分支保護設定也可能會擋下這類推送。

Force push 可能會讓遠端分支失去本機歷史中沒有的 commit。因此,要改寫共用分支,必須先由團隊另外討論並取得共識。一般修正請使用新的 commit 或 Revert。

通常值得討論 force push 的情形,是您自己的分支在團隊同意下改寫了歷史。即使如此,也要先確認沒有其他人新增的 commit。--force-with-lease 會額外檢查遠端分支是否仍處於預期狀態,但您還是得弄清楚哪些 commit 會被替換。

截圖中的 Force Push 位於 Push 按鈕的下拉選單。使用前,請確認您所用的 IDE 版本會採用哪種強制推送模式。

Force Push 按鈕

如果您還不完全確定自己要做什麼,就別使用 force push。建立新的修正 commit(或使用 Revert)會更安全。

Claude Code 的相關注意事項

這項原則對您和 Claude Code 都一樣:改寫共用歷史很危險。別把 force push 當成例行操作,也不要讓代理在共用分支上執行。如果 Claude 建議執行會改寫伺服器歷史的操作,請先停下來確認有沒有安全的替代方案(新的 commit、Revert)。

更新專案

開始新工作前,請確認基礎分支和未完成的變更。需要時取得更新,並檢視整合結果。Update Project 不保證一定不會發生衝突,而且會依據設定使用 merge 或 rebase。

更新後,請檢查目前分支、commit 清單和檔案狀態。如果出現衝突,先處理完再繼續工作。

Git Log 快顯選單

開啟 Git -> Log 分頁,再對任一 commit 按右鍵,就會出現一份很長的快顯選單。我們按用途分類,看看其中幾個最實用的指令。

"Git Log 快顯選單"章節插圖

第 1 組 - 檢視與分析(安全操作)

  • Copy Revision Number - 將 commit 的唯一 hash 複製到剪貼簿。您可以把 commit 連結傳給同事,或在任務(Jira、YouTrack)中引用;
  • Compare with Local - 比較舊 commit 中的檔案狀態與目前編輯器中的版本。想知道這段程式碼一個月前長什麼樣子,這招很方便;
  • Show Repository at Revision - 開啟 commit 當時專案中所有檔案的結構(不會切換目前分支)。

第 2 組 - 操作分支

  • New Branch... - 直接從過去選定的 commit 建立新分支。當您已經往前做了很多,才發現全都弄壞了,想從最後一個正常狀態重新開分支時,這個功能很實用;
  • Checkout Revision - 將本機專案切換到這個 commit。此時會進入 分離 HEAD(detached HEAD)狀態:您可以執行舊版程式碼,但新 commit 不會連到任何分支。如果在 detached HEAD 中建立了需要的 commit,請先用新分支保存它們。要回到原本狀態,請 Checkout 一般分支(例如 main)。

第 3 組 - 修改與移動 commit

  • Cherry-Pick - 從另一個分支取出一個指定的 commit,並複製到目前分支。例如,同事在另一個分支修好了妨礙您工作的 bug,您可以 Cherry-Pick 那個 commit,而不必合併整個分支;
  • Edit Commit Message... - 如果 commit 還沒 Push,可以快速修改它的訊息。只想改文字時,比 Amend 更方便。

第 4 組 - 撤銷變更

前面已經詳細介紹過這些指令:

  • Reset Current Branch to Here... - 將目前分支移到這個 commit(改變從該分支可到達的歷史);
  • Revert Commit - 建立一個"反向 commit",用新的本機 commit 撤銷已變更的內容,之後再推送到伺服器;
  • Undo Commit... - 將本機 commit 還原成變更清單中的修改。

第 5 組 - 改寫歷史

選單裡還有 Squash Commits...(把多個 commit 合併成一個)、Drop Commits(從歷史中間移除 commit)和 Interactively Rebase from Here... 等指令。這些工具可用來精細整理本機歷史(Interactive Rebase)。

請留意

還在熟悉這些操作時,先盡量別用這些指令 - 它們可能改寫選取的 commit 和分支後續的歷史。在團隊工作中,大家會在送出 Pull Request 前整理尚未完成的本機分支,讓歷史更容易閱讀。

Git 是您的安全網

請依照工作目前的狀態選擇還原方式:未 commit 的檔案、本機 commit 和已推送的歷史記錄,需要不同的處理方式。先保存需要的版本,並在操作前檢視變更,比期待任何錯誤都能復原可靠得多。

Claude Code 如何搭配使用

Claude Code 在專案中工作時,這些工具就是您最主要的保護。實際使用時,記得幾件事:

  • 經常建立 commit:每個 commit 都是可返回的節點。如果代理走錯方向,您可以回到最近一次正常狀態;
  • 要撤銷尚未 commit 的修改,先區分要保留的變更,再確認 Rollback 或 git restore 的作用範圍和還原來源;
  • 如果已建立 commit 但還沒推送,Undo Commit 會把變更放回編輯器;
  • 如果錯誤已經在伺服器上,建立新的修正 commit 或使用 Revert,會比改寫歷史安全。
請留意

別在沒看清楚前就同意刪除資料或改寫歷史的操作(Reset hard、force push)。先看看 Claude Code 準備做什麼。開始大型工作前,保存需要的狀態,並確認返回點真的包含您的工作。

上一篇:Pull request:從建立到合併 · 下一篇:建立 repo、rebase 與機密資料