查閱了一些資料,站在前人的肩膀上,看世界會很美好的。而且事實證明,如果英語好的話,基本學這個很快的,只要在git環境下分別輸入命令
git reset --help
git revert --help
就會打開對于這個命令的最官方的介紹了,相當詳細,包括用法,用時的目的和例子等等,只有一個點,我看不懂,都是英文。這就尷尬了,然后又只能偷懶又搜了其他國人大神的資料了。然后,正題開始了,用git寫博客啊做項目啊等等吧,有時候會弄出錯誤來,并且更新提交了,這時候怎么辦?這就需要用到我們要講的命令了。
reset(版本回撤)
開頭說的那樣,輸入help的命令,然后會自動打開個網頁,如截圖:

然后明白了,這一堆東西就是git reset相關命令的參數或者格式了。
</p>
這一堆東西怎么解析了?參閱資料,總結出來,其用法:
git reset --mixed
回退commit,保留源碼,默認方式。
git reset --soft
回退至某個版本,只回退commit信息
git reset --hard
徹底回退到某個版本
那么:
問題來了!!什么意思啊,什么時候用哪個呢?我需要引入一些概念和名詞的:
HEAD
這是當前分支版本頂端的別名,也就是在當前分支你最近的一個提交Index
index也被稱為staging area,是指一整套即將被下一個提交的文件集合。他也是將成為HEAD的父親的那個commitWorking Copy
working copy代表你正在工作的那個文件集Flow
當你第一次checkout一個分支,HEAD就指向當前分支的最近一個commit。在HEAD中的文件集(實際上他們從技術上不是文件,他們是blobs(一團),但是為了討論的方便我們就簡化認為他們就是一些文件)和在index中的文件集是相同的,在working copy的文件集和HEAD,INDEX中的文件集是完全相同的。所有三者(HEAD,INDEX(STAGING),WORKING COPY)都是相同的狀態,GIT很happy。
當你對一個文件執行一次修改,Git感知到了這個修改,并且說:“嘿,文件已經變更了!你的working copy不再和index,head相同!”,隨后GIT標記這個文件是修改過的。
然后,當你執行一個git add,它就stages the file in the index,并且GIT說:“嘿,OK,現在你的working copy和index區是相同的,但是他們和HEAD區是不同的!”
當你執行一個git commit,GIT就創建一個新的commit,隨后HEAD就指向這個新的commit,而index,working copy的狀態和HEAD就又完全匹配相同了,GIT又一次HAPPY了。
下面這一段是另外一個牛人的解釋:
總的來說,git reset命令是用來將當前branch重置到另外一個commit的,而這個動作可能會將index以及work tree同樣影響。
打住這些牛人的專業術語,容易蒙圈圈的,我換成自己的理解吧。
head就是當前分支下,最新一次提交commit之后本地庫對所有commit的總記錄里的最后一個commit記錄了。
index就是git add 命令后得到的暫存區的標記綜合了。
flow就是運行git status 然后沒有報出有改動,commit提交也是毫無變化的樣子。
重點來了:
記住git reset不會產生commits,它僅僅更新一個branch(branch本身就是一個指向一個commit的指針)指向另外一個commit(Head和branch Tip同時移動保持一致).其他的僅剩對于index和work tree(working directory)有什么影響。git checkout xxxCommit則只影響HEAD,如果xxxCommit和一個branch tip是一致的話,則HEAD和branch相匹配,如果xxxCommit并不和任何branch tip相一致,則git進入detached HEAD 狀態。
我的理解:
就是commits是所有變化狀態的合集,git reset只是使branch tip狀態也就是head,從當前狀態變到合集里的任一子集元素,只是限于單單這種操作, 合集本身沒有變化啊,好比在一條直線路上行進的車,車再怎么前進或后退,路本身沒變的。checkout可以把當前的head轉到另一分支上,而對于當前的master來說基本沒有變。
如果你仔細研究reset命令本身就知道,它本身做的事情就是重置HEAD(當前分支的版本頂端)到另外一個commit。
具體命令:
- 回退所有內容到上一個版本
git reset HEAD^
- 回退a.py這個文件的版本到上一個版本
- 向前回退到第3個版本
git reset –soft HEAD~3
- 將本地的狀態回退到和遠程的一樣
git reset –hard origin/master
- 回退到某個版本
分析下soft和hard的區別
- soft參數告訴Git重置HEAD到另外一個commit,但也到此為止。如果你指定--soft參數,Git將停止在那里而什么也不會根本變化。這意味著index,working copy都不會做任何變化,所有的在original HEAD和你重置到的那個commit之間的所有變更集都放在stage(index)區域中。
也就是我上面自己的理解那里的意思,大白話,好懂。
hard參數將會blow out everything.它將重置HEAD返回到另外一個commit(取決于~12的參數),重置index以便反映HEAD的變化,并且重置working copy也使得其完全匹配起來。這是一個比較危險的動作,具有破壞性,數據因此可能會丟失!如果真是發生了數據丟失又希望找回來,那么只有使用:[git reflog]命令了。你的所有本地修改將丟失。如果我們希望徹底丟掉本地修改但是又不希望更改branch所指向的commit,則執行git reset --hard = git reset --hard HEAD. i.e. don't change the branch but get rid of all local changes.另外一個場景是簡單地移動branch從一個到另一個commit而保持index/work區域同步。不過它將修改你的work tree。
這是說hard操作就是以commit合集中的某一元素作為head 的落腳點,并且以它為藍本,毀掉暫存區記錄,本地庫和遠程庫記錄,包括源文件,只是為了這一藍本服務,就好像議會制國家里,輪流執政,突然其中一個議員搞成了中央集權,所有的都向他同化了。mixed是reset的默認參數,也就是當你不指定任何參數時的參數。它將重置HEAD到另外一個commit,并且重置index以便和HEAD相匹配,但是也到此為止。working copy不會被更改。所有該branch上從original HEAD(commit)到你重置到的那個commit之間的所有變更將作為local modifications保存在working area中,(被標示為local modification or untracked via git status),但是并未staged的狀態,你可以重新檢視然后再做修改和commit。
總結
其實就是--soft 、--mixed以及--hard是三個恢復等級。使用--soft就僅僅將頭指針恢復,已經add的緩存以及工作空間的所有東西都不變。如果使用--mixed,就將頭恢復掉,已經add的緩存也會丟失掉,工作空間的代碼什么的是不變的。如果使用--hard,那么一切就全都恢復了,頭變,aad的緩存消失,代碼什么的也恢復到以前狀態。
revert(撤消操作)
撤銷某次操作,此次操作之前的commit都會被保留。 git reset 是撤銷某次提交,但是此次之后的修改都會被退回到暫存區。
格式
如圖
實例
git revert HEAD~3
丟棄最近的三個commit,把狀態恢復到最近的第四個commit,并且提交一個新的commit來記錄這次改變。
git revert -n master~5..master~2
:丟棄從最近的第五個commit(包含)到第二個(不包含),但是不自動生成commit,這個revert僅僅修改working tree和index。
reset與revert的區別
- git revert是用一次新的commit來回滾之前的commit,git reset是直接刪除指定的commit。
- 在回滾這一操作上看,效果差不多。但是在日后繼續merge以前的老版本時有區別。因為git revert是用一次逆向的commit“中和”之前的提交,因此日后合并老的branch時,導致這部分改變不會再次出現,但是git reset是之間把某些commit在某個branch上刪除,因而和老的branch再次merge時,這些被回滾的commit應該還會被引入。
- git reset 是把HEAD向后移動了一下,而git revert是HEAD繼續前進,只是新的commit的內容和要revert的內容正好相反,能夠抵消要被revert的內容。
最后感謝前輩大神們的資料素材,好多都是我用拿來主義,現學現賣的。主要參考《git中reset與revert的使用》和《git reset soft,hard,mixed之區別深解》。
實際操作及用法練習
首先在本地庫操作,新建了文件haha.txt,然后依次做出六次添加單詞,每次加一個,每次都會提交commit。然后用log命令查看所有的變動記錄,如圖:
然后再次提交commit,標簽是shuaxin,這樣log 記錄里的排行分別向下推一位了。
- revert操作
git revert HEAD~2
實際目標就是丟棄shuaxin 和oh ,然后以標簽yes的那個狀態存在,并且再次提交commit,log會記錄這次commit的。