首先,我们先弄清楚几个定义:
- HEAD(头)
HEAD 是当前分支引用的指针,它总是指向该分支上的最后一次提交。 这表示 HEAD 将是下一次提交的父结点。 通常,理解 HEAD 的最简方式,就是将它看做 你的上一次提交 的快照 - Index (索引)
也可以被认为是staging area(暂存区),是一堆将在下一次commit中提交的文件,提交之后,它就是HEAD的父节点(git add添加的文件) - working copy (工作副本)
当前工作目录下的文件(一般指,有修改,没有git add,没有git commit的文件)
Flow (流程如下)
- 当你第一次checkout一个新的分支,HEAD指向该分支上最近一次commit。它和index和working copy是一样一样的。
- 当你修改了一个文件,Git注意到了会说“哦,有些东西被改了”,你的working copy不再和index和HEAD相同了,所以当文件有改动,它会标记这些文件。
- 然后,你执行git add命令,这条命令会将上面修改的文件缓存在index中,Git又说了“哦,你的working copy和index相同了,而他们俩和HEAD不同了”。
- 当你执行git commit,Git创建了一个新的commit,HEAD这时指向这个新的commit,此时,HEAD & index & working copy又相同了。
reset(重置)
-
但是,我们写代码,总有犯错的时候,如果不满意这次修改,想要回退到上一次提交,怎么办? 这个时候,有几个命令可以帮助到我们!
git reset --hard
git reset --soft
git reset --mixed
-
git reset --hard
这个命令非常危险,是git中,少有几个会丢失信息的操作,会直接删除掉目标HEAD之后所有的操作,且工作去和暂存区都会修改
看下边的例子,这是修改前的远程仓库,和修改前的本地仓库
image.png
image.png
然后我在本地仓库新建一个b.md, 并git add 到暂存区,但是并没有提交
image.png
然后执行 git reset -- hard 命令 ,执行命令后,工作区,暂存区,和远程库又保持一致了,回到了上一次commit 的状态
image.png git reset --soft
soft参数,告诉Git重置HEAD到另外一个commit,但也到此为止。如果你指定--soft参数,Git将停止在那里而什么也不会根本变化。这意味着index,working copy都不会做任何变化,所有的在original HEAD和你重置到的那个commit之间的所有变更集都放在stage(index)区域中。git reset --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
git revet
git revert 撤销 某次操作,此次操作之前和之后的commit和history都会保留,并且把这次撤销
- git revert HEAD 撤销前一次 commit
- git revert HEAD^ 撤销前前一次 commit
- git revert commit (比如:fa042ce57ebbe5bb9c8db709f719cec2c58ee7ff)撤销指定的版本,撤销也会作为一次提交进行保存。
- git revert是提交一个新的版本,将需要revert的版本的内容再反向修改回去,版本会递增,不影响之前提交的内容
git revet 和 git reset的区别
- 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的内容。