git reset soft,hard,mixed之區別深解

GIT reset命令,彷佛讓人很迷惑,以致於誤解,誤用。可是事實上不該該如此難以理解,只要你理解到這個命令究竟在幹什麼。git

首先咱們來看幾個術語app

  • HEAD

這是當前分支版本頂端的別名,也就是在當前分支你最近的一個提交spa

  • Index

index也被稱爲staging area,是指一整套即將被下一個提交的文件集合。他也是將成爲HEAD的父親的那個commit.net

  • Working Copy

working copy表明你正在工做的那個文件集3d

  • Flow

當你第一次checkout一個分支,HEAD就指向當前分支的最近一個commit。在HEAD中的文件集(實際上他們從技術上不是文件,他們是blobs(一團),可是爲了討論的方便咱們就簡化認爲他們就是一些文件)和在index中的文件集是相同的,在working copy的文件集和HEAD,INDEX中的文件集是徹底相同的。全部三者(HEAD,INDEX(STAGING),WORKING COPY)都是相同的狀態,GIT很happy。指針

當你對一個文件執行一次修改,Git感知到了這個修改,而且說:「嘿,文件已經變動了!你的working copy再也不和index,head相同!」,隨後GIT標記這個文件是修改過的。code

而後,當你執行一個git add,它就stages the file in the index,而且GIT說:「嘿,OK,如今你的working copy和index區是相同的,可是他們和HEAD區是不一樣的!」blog

當你執行一個git commit,GIT就建立一個新的commit,隨後HEAD就指向這個新的commit,而index,working copy的狀態和HEAD就又徹底匹配相同了,GIT又一次HAPPY了。ip

下面這一段是另一個牛人的解釋:get

總的來講,git reset命令是用來將當前branch重置到另一個commit的,而這個動做可能會將index以及work tree一樣影響。好比若是你的master branch(當前checked out)是下面這個樣子:

- A - B - C (HEAD, master)

HEAD和master branch tip是在一塊兒的,而你但願將master指向到B,而不是C,那麼你執行

git reset B以便移動master branch到B那個commit:

- A - B (HEAD, master)      # - C is still here, but there's no branch pointing to it anymore

注意:git reset和checkout是不同的。若是你運行git checkout B,那麼你講獲得:

- A - B (HEAD) - C (master)

這時HEAD和master branch就不在一個點上了,你進入detached HEAD STATE. HEAD,work tree,index都指向了B,可是master branch卻依然指向C。若是在這個點上,你執行一個新的commit D,那麼你講獲得下面(固然這可能並非你想要的,你可能想要的是創一個branch作bug fix):

- A - B - C (master)
       \
        D (HEAD)

記住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 狀態

 

 

  • Reset

若是你仔細研究reset命令自己就知道,它自己作的事情就是重置HEAD(當前分支的版本頂端)到另一個commit。假設咱們有一個分支(名稱自己無所謂,因此咱們就簡單稱爲"super-duper-feature」分支吧),圖形化表示以下:

若是咱們執行:

git reset HEAD

任何事情都不會發生,這是由於咱們告訴GIT重置這個分支到HEAD,而這個正是它如今所在的位置。

git reset HEAD~1

當咱們再執行上面的命令時(HEAD~1是「the commit right before HEAD」的別名,或者說:put differently "HEAD's parent"),咱們的分支將會以下所示

若是咱們執行git reset HEAD~2,則意味着將HEAD從頂端的commit往下移動兩個更早的commit。

  • Parameters
  1. soft

--soft參數告訴Git重置HEAD到另一個commit,但也到此爲止。若是你指定--soft參數,Git將中止在那裏而什麼也不會根本變化。這意味着index,working copy都不會作任何變化,全部的在original HEAD和你重置到的那個commit之間的全部變動集都放在stage(index)區域中。

 

  2.hard

--hard參數將會blow out everything.它將重置HEAD返回到另一個commit(取決於~12的參數),重置index以便反映HEAD的變化,而且重置working copy也使得其徹底匹配起來。這是一個比較危險的動做,具備破壞性,數據所以可能會丟失!若是真是發生了數據丟失又但願找回來,那麼只有使用:git reflog命令了。makes everything match the commit you have reset to.你的全部本地修改將丟失。若是咱們但願完全丟掉本地修改可是又不但願更改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!

  3.mixed(default)

--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

相關文章
相關標籤/搜索