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

相关文章
相关标签/搜索