By francis_hao Nov 21,2016
從版本庫初始化開始,每一步的撤銷操作
添加第一個文件
在空的版本庫中創建了一個文件並git add到了緩存區,這時候怎么撤銷呢?
撤銷單個文件和整個目錄
$ git rm --cached a
$ git rm --cached . -r
首次commit內容不能撤銷,不過一旦提交了一次之后,git就能發揮它強大的版本控制作用了
修改了文件
在本地修改了文件,但是還沒有add操作,也就是撤銷本地的修改
撤銷單個文件和整個目錄,"--"雖然可以省略,但還是以規范為重。表示檢出文件,而不是分支
$ git checkout -- a
$ git checkout -- .
add了修改的文件
將修改的文件add到了緩存區,后悔了想撤銷但本地的修改不變
撤銷單個文件和整個目錄
$ git reset HEAD c
$ git reset HEAD .
reset有幾種模式,默認模式為mixed,也就是將版本庫和緩存區里的重置,但本地文件不動。
commit了修改的文件
將修改的文件commit到版本庫里了,若需要撤回到之前的版本,如下圖,共有5次提交,目前在E位置,想回到C位置
$ git reset --hard C_value
這樣就直接回到C位置,后面的兩次提交被舍棄了。當然還可以通過git reflog查看哈希值再返回。
還有一種方式是,HEAD保留在E位置,但是,工作目錄里的所有文件替換稱C位置的。
$ git checkout C_value -- .
撤銷某次提交
還是以上面的5次提交為例,發現在C提交的內容中引入了錯誤,需要取消C的提交,但是C之后的D和E提交需要保留。
以我的理解,git的具體做法是將B、C和E三者進行比較(至於如何比較參考下文附注),如果可以合並,git會自動合並,如果不能自動合並,就需要手動解決沖突了。
$ git revert C_value
如果有沖突,不想解決,想取消revert
$ git revert --abort
有沖突,解決了之后
$ git add <file_that_conflict>
$ git revert --continue
其中add為了讓git知道沖突已經解決了,根據需要add也許是rm或mv
附注
在使用git revert時,有一個問題困擾了我很久,就是git是如何實現合並的,因為有時候覺得明明可以合並的卻出現了沖突,下面以幾個實驗說明自己的猜想
自動合並成功舉例
第一個例子是可以成功合並的,沒有沖突發生,選取了B、C、D和E四個位置的文件內容。其中D位置認為沒有作用。認為文件有兩處差別,分別用1和2表示,1B表示第一處差別的B位置。
合並后的結果如下
根據合並后的結果推斷合並過程
1B≠1C=1E =>差別刪除
2B=2C≠2E =>差別保留
自動合並失敗舉例
第二例自動合並失敗,提示有沖突,此處認為僅有一處差別
推斷合並過程
1B≠1C≠1E =>自動合並失敗
自動合並成功-補充
本例也是和並成功的例子,和第一例不同處僅僅為1C處的修改,但並不會影響結果。是不是就可以說明D位置不會參與比較合並的過程呢?
本文由 劉英皓 創作,采用 知識共享 署名-非商業性使用-相同方式共享 3.0 中國大陸 許可協議進行許可。歡迎轉載,請注明出處:
轉載自:http://www.cnblogs.com/yinghao1991/p/6091613.html
參考
[1] git help revert
[2] 廖雪峰 http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000 Git教程
[3] geeeeeeeeek/git-recipes https://github.com/geeeeeeeeek/git-recipes/wiki/ 代碼回滾:Reset、Checkout、Revert的選擇