摘自《Git權威指南》
Git reset 是Git最常用的命令之一,也是最危險最容易誤用的命令。
用法一:git reset [-q] [<commit>] [--] <paths>...
用法二:git reset [--soft --mixed | --hard | --merge | --keep] [-q] [<commit>]
以上兩種用法,<commit>都是可選項,可以使用下引用或提交ID,如果省略則相當於使用了HEAD的指向作為提交ID。
上面的兩種用法的區別在於,第一種在命令中包含路徑<paths>。為了避免路徑和引用(或者提交ID)同名而發生沖突,可以在<paths>前用兩個連續的短線(減號)作為做分隔。
第一種用法(包含了路徑<paths>的用法)不會重置引用,更不會改變工作區,而是用指定提交狀態(<commit>)下的文件(<paths>)替換掉暫存區中的文件。例如命令git reset HEAD <paths>相當於取消之前執行的git add <paths>命令時改變的暫存區。
第二種用法(不使用路徑<paths>的用法)則會重置引用。根據不同的選項,可以對暫存區或工作區進行重置。參照下面的版本庫模型圖,來看一看不同的參數對第二種重置語法的影響。
命令格式:git reset [--soft | --mixed | --hard] [<commit>]
1)使用參數--hard,如git reset --hard <commit>
會執行上圖中的全部動作①、②、③,即:
①替換引用的指向。引用指向新的提交ID。
②替換暫存區。替換后,暫存區的內容和引用指向的目錄樹一致。
③替換工作區。替換后,工作區的內容變得和暫存區一致,也和HEAD所指向的目錄樹內容相同。
2)使用參數--soft,如 git reset --soft <commit>
會執行上圖中的操作①。即只更改引用的指向,不改變暫存區和工作區。
3)使用參數--mixed或者不使用參數(默認為--mixed),如 git reset <commit>
會執行上圖中的操作①和②。即更改引用的指向及重置暫存區,但是不改變工作區。
下面通過一些示例,看一下重置命令的不同用法。
$ git reset
僅用HEAD指向的目錄樹重置暫存區,工作區不會受到影響,相當於將之前用git add 命 令更新到暫存區的內容撤出暫存區。引用也未改變,因為引用重置到HEAD相當於沒 有重置。
$ git reset HEAD
同上
$ git reset -- filename
僅將文件filename 的改動撤出暫存區,暫存區中其他文件不改變。相當於命令git add filename 的反射操作。
$ git reset HEAD filename
同上。
$ git reset --soft HEAD^
工作區和暫存區不改變,但是引用向前回退一次。當對最新的提交說明或者提交的更改不滿意時,撤銷最新的提交以便重新提交。
之前提到過修補提交命令git commit --amend,用於對最新的提交進行重新提交以修補錯誤的提交說明或者錯誤的提交文件。修補提交命令實際上相當於執行了下面兩條命令。(注:文件.git/COMMIT_EDITMSG保存了上次的提交日志)
$ git reset --soft HEAD^
$ git commit -e -F .git/COMMIT_EDITMSG
$ git reset HEAD^
工作不改變,但是暫存區會回退到上一次提交之前,引用也會回退一次。
$ git reset --mixed HEAD^
同上
$ git reset --hard HEAD^
徹底撤銷最近的提交。引用回退到前一次,而且工作區和暫存區都會回退到上一次提交的狀態。自上一次以來的提交全部丟失。