查阅了一些资料,站在前人的肩膀上,看世界会很美好的。而且事实证明,如果英语好的话,基本学这个很快的,只要在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的。