一:reset 和 revert的区别
Reset是回退到某个指定的节点,往后的一律消失;
Revert是撤回某个指定的节点,剩下的提交记录都还在,包括操作的revert节点;
二:谈谈Reset 涉及的属性
举例:
新建一个文件,并输入文字然后提交:
GIT查看提交记录就会出现第一次提交:
提交后查看远程仓库目录及文件内容:
[图片上传失败...(image-61bd8f-1641457575108)]
再次修改readme.txt文件,并提交到远程仓库
[图片上传失败...(image-ce7452-1641457575107)]
[图片上传失败...(image-25c576-1641457575107)]
查看远程仓库是否正确提交:
[图片上传失败...(image-fc0b3d-1641457575107)]
[图片上传失败...(image-dd4ac9-1641457575107)]
现在再新增一个test.html文件,并把他推送到远程仓库
[图片上传失败...(image-f5673a-1641457575106)]
[图片上传失败...(image-e006bf-1641457575106)]
再次查看远程仓库和提交记录
[图片上传失败...(image-7ab916-1641457575106)]
[图片上传失败...(image-6807f2-1641457575106)]
这时需要变更:不要test也不要readme上的第二次修改的内容,需要版本回退到第一次提交的‘T1’,那用reset操作 → git reset --hard commitId
[图片上传失败...(image-1d6562-1641457575106)]
此时本地test已删除,readme也回到了第一次提交的记录,但是查看远程依然是最新的代码并没有回退,那么需要本来push来更新。
[图片上传失败...(image-5c31bf-1641457575106)]
[图片上传失败...(image-3f38e0-1641457575106)]
当我执行git push会失败,因为本地代码回到了旧版本,但远程仓库是新版本和本地不一致,所以当我用git push时会报错,这里我们需要使用强制提交:git push -f
[图片上传失败...(image-e3f84a-1641457575106)]
再看远程仓库已回退
[图片上传失败...(image-e7e651-1641457575106)]
这个时候看提交记录也回到了第一次提交,后面的记录都没了
[图片上传失败...(image-294a32-1641457575106)]
可见,reset是彻彻底底的回退,该commit之后的所有修改将完全消失,包括提交记录。
Reset hard的其他几种回退方法:
git reset --hard HEAD^
git reset --hard HEAD~2
^的个数/~2表示回退的个版本个数
优点:
彻底回退到指定版本,代码提交记录干净清爽;
提交时间线也清晰没有冗杂;
缺点:
记录彻底清除,无法再次恢复;
- git reset --soft commitId, 还原到暂存区
[图片上传失败...(image-1c8975-1641457575105)]
- git reset --mixed commitId, 把文件还原到工作区
[图片上传失败...(image-6dfee9-1641457575105)]
三:谈谈Revert:
revert执行后会产生新的commit记录,是通过一次新的commit来恢复到之前旧的commit,但revert会保留恢复的该次提交后面的其它提交内容,假如后面的提交与要恢复的提交更改了同一地方,此时用revert就会产生冲突!
我们把上面的三次提交再操作一次;
[图片上传失败...(image-c62a58-1641457575105)]
[图片上传失败...(image-21d1da-1641457575105)]
[图片上传失败...(image-dd070c-1641457575105)]
此时我们用reset的思路来回退到第一次提交,命令行 → Git revert commitId
[图片上传失败...(image-f0e78b-1641457575105)]
如上所示冲突了,当前内容是第2次提交,而我们要恢复的内容是read 1
如果对revert命令没有深入了解的话,就可能会产生疑惑,为什么会冲突?而且我实际上是想像reset一样恢复或者说是回退到T1(这里要再次说明一下第一次提交的状态:只有一个readme文件,且内容是第一次提交),但为什么冲突提示要恢复到read 1.???这是初始第一次写的。
其实,准确来说,revert是撤销/撤回/反提交的意思,我们不能按reset的思路理解,我们执行git revert T1,这么做其实结果是要撤销第一次的提交,注意,仅仅是撤销T1的提交,把T1的修改恢复到T1之前也就是初始的状态,而不会影响T2,T3的提交。但如果T2,T3中修改了T1修改的同一地方,那么就会产生冲突,因为revert意图撤销T1的修改,但发现T2和T3把T1的修改再次修改了,此时,revert意图变得不清晰,因为它无法确定到底是应用你最新的修改,还是恢复到初始状态,这将由你来决定!
那如果我们要恢复T1的状态,那需要撤销T2来对T1进行修改 git revert T2:
[图片上传失败...(image-1eab7-1641457575104)]
这里需要我们修改或输入提交日志,按 “i”,进入输入状态,写完后按ESC退出输入状态,再按“:wq”退出!
成功后,执行 git push:
[图片上传失败...(image-796d41-1641457575104)]
查看远程仓库,也已撤回T2,readme已回到想要的状态:
[图片上传失败...(image-aa6264-1641457575104)]
[图片上传失败...(image-767b4c-1641457575104)]
可见,revert操作成功后,产生了新的commit记录,T2对T1的修改已经恢复,现在的readme就是t1提交后的状态,但同时demo文件仍然存在,即T3的提交不受影响!
[图片上传失败...(image-d1945d-1641457575104)]
[图片上传失败...(image-990b08-1641457575104)]
但如果你说,想要和reset一样,把t2t3的提交也要删除掉,那你就先revert t3,再revert t2,可以达到同样的效果,但这样一来,为何不直接用reset?如果你说既想达到reset的效果,又想有记录防止反悔,那这。。。是一个值得思考的问题!
总结:
reset是彻底回退到指定的commit版本,该commit后的所有commit都将被清除,包括提交历史记录;
revert仅仅是撤销指定commit的修改,并不影响后续的commit,但所撤销的commit被后续的commit修改了同一地方则会产生冲突;
reset执行后不会产生记录,revert执行后会产生记录;
reset执行后无法再次恢复,revert执行后因为不会清除记录,并且会产生新纪录,所以文件不会丢失,你可以多次执行revert恢复到某次改变之前的状态;
reset执行后HEAD会后移,而revert的HEAD则一直是向前的;
理清了reset和revert的基本原理,你就明白了在什么时间该使用哪个命令更为合适了!
[图片上传失败...(image-a84b6a-1641457575104)]
- Checkout
Git checkout -- 文件名
Reset hard HEAD 文件名,只能在工作区才能起效果。
扩展插件:
SpanTree-gitlab tree
[图片上传失败...(image-2dbc91-1641457575104)]
[图片上传失败...(image-ef4577-1641457575104)]
这样查看文件就可以方便很多。