git reset详解

HEAD

HEAD也是不少初学者会搞不清楚的一个概念 说穿了也很简单 就是git

你的目前branch的最新的commit
假设这是目前的git log, HEAD指向master的最新的commitspa

因此今天你下了git checkout b1
HEAD就会指向你checkout的那个branch的tip翻译

但有个例外 由于checkout并不仅能够指定branch 还能够指定一个commit 因此当你checkout <commit>
clipboard.pngcode

他的意思是说 嘿 既然你指定的是commit 我就生一个暂时的branch给你 你如今的确在一个branch上 只是这个branch没有名字 你能够立刻checkout -b 生出一个branch 也能够commit在这个没有名字的branch上面
clipboard.pngip

再说一次 HEAD就是你的目前branch的最新的commit 即便这个branch可能没有名字开发

git reset

git reset [ –soft | –mixed | –hard] <commit>

git reset <commit> 的意思就是 把HEAD移到<commit>rem

这是如今repo的状况
clipboard.pngget

D在stage裡面, E在working裡it

我习惯想像成这样 红色就是还没进staging 绿色就是还没commit
clipboard.pngast

这裡的repo是指local的 不是remote的 别忘了一个铁则 Working >= Staging >= Repo

这样具体化以后 以后的解释会简单不少

再说一次 git reset <commit> 的意思就是 把HEAD移到<commit> 就是把你如今这个branch的最新的commit移到你指定的commit

soft就是只动repo
mixed就是动repo还有staging(这个是默认参数)
hard就是动repo还有staging还有working

你只要知道这三种用法就能够

如今的State是S0 由于等一下会一直回到如今的state, S0的HEAD在Repo的C

SOFT

soft 就是只动repo

这样子 staging裡面就会有c和d, working 裡e同样

git reset --soft <B commit>

clipboard.png

HEAD会跑到repo的B

MIXED/DEFAULT

状态回到S0

mixed就是动repo还有staging

这样子 staging裡面就什麽都没有, working 裡c,d,e

git reset --mixed <B commit>

clipboard.png

HEAD会跑到repo的B

HARD

状态回到S0

hard就是动repo还有staging还有working

这样子 staging裡面就什麽都没有, working 裡什麽都没有

git reset --hard <B commit>

clipboard.png

HEAD会跑到repo的B

git reset第二种用法

git reset <commit> [--] <file>

第二种的用法只是第一种的一个特例 就是前面的soft/mixed/hard不能指定 使用默认的mixed

而后后面能够指定单独的file

(先不要管[--])这个用法就是你能够只针对一个file作出这个指令

git reset --mixed <commit>

至于--(double hyphen) 是避免有些人会把档案名称取的跟branch名称同样 或是你有个档案就叫作"HEAD" 你就必须用 -- HEAD 而不是只用HEAD 但基本上你不胡搞 你是不须要用到这个的

还有一件事 若是你commit不给 default就是HEAD, 若是你file不给 default就是整个资料夹

恭喜走出十里坡
基本上git reset已经讲完了 你看到一个git reset的command你就知道执行下去会发生什麽事 但看到command知道会发生什麽事只是学git的第一步而已 你要知道什麽时候要用这个command才是高手 如下说明常遇到 须要用git reset的例子

扩展阅读(实例说明)

Unstage
有没有看到那精美的

(use "git reset HEAD ..." to unstage)

为什麽能够呢 由于default是–mixed 因此白话文就是把HEAD移到HEAD(就是不要动的意思) 而后staging跟著变 这就表明把staging的状态跟HEAD的状态搞成同样

因此要是从S0下这个指令

git reset HEAD d
会变这样
clipboard.png

虽然会变成这样是由于staging变得跟repo同样 但你用git status看一下
clipboard.png

感受会像是d从staging变到working去了 因此结果看起来像是"unstage"

固然你要unstage全部的file就是

git reset HEAD
触类旁通 你要unstage并且要把他们从working拿掉 就是

git reset --hard HEAD
Undo commit
这大概是首屈一指常见的问题 stackoverflow上问如何undo last commit的这题有一万多个讚 事实上也很简单 本来状态是这样
clipboard.png
下这个指令后

git reset --soft HEAD~
就变这样 轻松
clipboard.png

在错的branch上开发
还有一个蛮常见的状况 你要开发前要先跟远端的origin/master sync, sync完后你忘记换到本身的feature branch而是直接在master上开发 写了两个commit后忽然发现写错branch 该怎麽办呢

如今状况是这样
clipboard.png

git branch feature_branch
複製一个新的branch 变成这样
clipboard.png

git reset --hard origin/master
clipboard.png

git checkout feature_branch
clipboard.png

Squash commit
另外一个用法 也是我写这篇文章的缘由 是我上礼拜要check in个人code进prod的时候 我必须把我全部local的commit变成一个commit 咱们组的Tech lead问我说该怎麽作 我跟他说 嘿嘿我知道 用git interactive rebase 他说那个比较麻烦 要选来选去 只要下一个简单的git reset就能够 我才大彻大悟 原来以前作学问没有读通 把简单的事搞複杂了

假设如今要把CDE squash成一个commit push到remote 如今状态是这样
clipboard.png

这时候下个精美的

git reset --soft HEAD~3
就会变这样
clipboard.png

那事实上上面那张跟下面那张是同一件事
clipboard.png

再下个git commit就搞定了

最后一题
最后来考一下这题 看你们是否是真的懂 当心是个陷阱题

这是如今的State:
clipboard.png

请问下完这个command以后

git reset --hard HEAD~1
会变成什麽样子呢

(A)
clipboard.png
(B)
clipboard.png
(C)
clipboard.png

答案是B 你答对了吗?

via:来源翻译自jyt0532 的 Git reset

相关文章
相关标签/搜索