如何撤銷 Git 操作?

阮一峰發表於2019-12-24

Git 版本管理時,往往需要撤銷某些操作。

本文介紹幾種最主要的情況,給出詳細的解釋。更多的命令可以參考《常用 Git 命令清單》一文。

一、撤銷提交

一種常見的場景是,提交程式碼以後,你突然意識到這個提交有問題,應該撤銷掉,這時執行下面的命令就可以了。


$ git revert HEAD

上面命令的原理是,在當前提交後面,新增一次提交,抵消掉上一次提交導致的所有變化。它不會改變過去的歷史,所以是首選方式,沒有任何丟失程式碼的風險。

git revert 命令只能抵消上一個提交,如果想抵消多個提交,必須在命令列依次指定這些提交。比如,抵消前兩個提交,要像下面這樣寫。


$ git revert [倒數第一個提交] [倒數第二個提交]

git revert命令還有兩個引數。

  • --no-edit:執行時不開啟預設編輯器,直接使用 Git 自動生成的提交資訊。
  • --no-commit:只抵消暫存區和工作區的檔案變化,不產生新的提交。

二、丟棄提交

如果希望以前的提交在歷史中徹底消失,而不是被抵消掉,可以使用git reset命令,丟棄掉某個提交之後的所有提交。


$ git reset [last good SHA]

git reset的原理是,讓最新提交的指標回到以前某個時點,該時點之後的提交都從歷史中消失。

預設情況下,git reset不改變工作區的檔案(但會改變暫存區),--hard引數可以讓工作區裡面的檔案也回到以前的狀態。


$ git reset --hard [last good SHA]

執行git reset命令之後,如果想找回那些丟棄掉的提交,可以使用git reflog命令,具體做法參考這裡。不過,這種做法有時效性,時間長了可能找不回來。

三、替換上一次提交

提交以後,發現提交資訊寫錯了,這時可以使用git commit命令的--amend引數,可以修改上一次的提交資訊。


$ git commit --amend -m "Fixes bug #42"

它的原理是產生一個新的提交物件,替換掉上一次提交產生的提交物件。

這時如果暫存區有發生變化的檔案,會一起提交到倉庫。所以,--amend不僅可以修改提交資訊,還可以整個把上一次提交替換掉。

四、撤銷工作區的檔案修改

如果工作區的某個檔案被改亂了,但還沒有提交,可以用git checkout命令找回本次修改之前的檔案。


$ git checkout -- [filename]

它的原理是先找暫存區,如果該檔案有暫存的版本,則恢復該版本,否則恢復上一次提交的版本。

注意,工作區的檔案變化一旦被撤銷,就無法找回了。

五、從暫存區撤銷檔案

如果不小心把一個檔案新增到暫存區,可以用下面的命令撤銷。


$ git rm --cached [filename]

上面的命令不影響已經提交的內容。

六、撤銷當前分支的變化

你在當前分支上做了幾次提交,突然發現放錯了分支,這幾個提交本應該放到另一個分支。


# 新建一個 feature 分支,指向當前最新的提交
# 注意,這時依然停留在當前分支
$ git branch feature

# 切換到這幾次提交之前的狀態
$ git reset --hard [當前分支此前的最後一次提交]

# 切換到 feature 分支
$ git checkout feature

上面的操作等於是撤銷當前分支的變化,將這些變化放到一個新建的分支。

(完)

相關文章