你晓得Git版本控制系统中都有哪些“后悔药”吗?本文通过案例解说
git reset 、 git revert 、 git checkout
在版本控制中的作用;
场景
小明同学作为新人退出到一个新的项目组中做开发,在我的项目的迭代开发中,小明勤勤恳恳的写代码,直到有一次...
小明:完了,完蛋了
洋仔:怎么了,一惊一乍的小明:我把错误代码用git commit后还push到线上代码库了! 这可怎么办!
洋仔:莫慌,git有“后悔药”!
洋仔:容我给你缓缓道来。 然而咱们要先晓得一些git的基础知识,你能力更好的了解git命令的作用
准备常识
git将我的项目的存储分为4局部,每局部有本人作用,
见下图:
Workspace
:工作区(以后用户操作批改的区域)Index / Stage
:暂存区 (add后的区域)Repository
:仓库区或本地仓库(commit后的区域)Remote
:近程仓库(push后的区域)
整体过程能够简述为:
- 工作区–>
add
–>暂存区–>commit
–>本地仓库区–>push
–>近程仓库区 - 近程仓库区–>
fetch
–>应用refsremotes下对应分支文件记录近程分支末端commit_id 和 本地仓库区 -->merge
–>工作区 - 近程仓库区–>
pull
–>应用refsremotes下对应分支文件记录近程分支末端commit_id and 本地仓库区 and 工作区
具体的git的组成部分和概念命令,请移步下述两个博客(超链接):
Git技术干货!工作中Git的应用实际和常用命令合集!
Git - 应用git不晓得外部实现机制怎么行
假如我的项目存在这么一个提交记录:
$ git logcommit commit_id4 (HEAD -> master)Author: testDate: Thu Aug 20 16:28:45 2020 +0800 第三次批改README文件commit commit_id3 (HEAD -> master)Author: testDate: Thu Aug 20 16:28:45 2020 +0800 第二次批改README文件commit commit_id2Author: testDate: Thu Aug 20 16:28:19 2020 +0800 第一次批改README文件commit commit_id1Author: testDate: Thu Aug 20 16:26:59 2020 +080 初始化我的项目
提交程序为:commit_id1
--> commit_id2
--> commit_id3
--> commit_id4
留神:在git中每次的commit都有一个commit id惟一标识以后的提交!
上面,咱们先来解决小明的这个问题,应用git reset
即可完满解决~
问题解决
洋仔:小明,你的这个就能够用git reset 这个命令来完满的搞定,上面咱们看一下如何解决
1、获取以后提交的commit id
命令:git log
获取到以后我的项目分支下的所有commit记录;
假如上述小明提交谬误的commit id为commit id:commit_id4
这一次提交;
他的上一次提交就是commit id:commit_id3
,咱们要将批改回滚到commit_id3
的时刻!
小明:我想要把我方才 commit的批改保留下来,我批改的代码不能给我删除掉呀!洋仔:没问题
2、将某个commit id前的commit革除,并保留批改的代码
命令:git reset <commit_id>
以后场景下就是:git reset commit_id3
将指定commit_id后的所有提交,都去除,并保留批改的代码在本地的区域,也就是Workspace
中
小明:啊哈,这样的话我就能够把错误代码批改后再提交了; 然而我曾经push到线上仓库的数据怎么办呢?洋仔:别急,有方法~
3、批改代码实现后,将批改好的代码add到暂存区,并提交到本地仓库中
命令:git add <file_name>
and git commit
以后场景下:git add .
and git commit
将最新批改后的代码commit
则提交后的提交记录假如如下: 能够看到,咱们谬误提交的commit_id4
提交记录隐没,取而代之的是咱们更新代码后提交的记录commit_id5
; 这样就实现了本地的代码批改和更新
$ git logcommit commit_id5 (HEAD -> master)Author: testDate: Thu Aug 20 16:28:45 2020 +0800 第三次批改README文件-更新谬误后提交commit commit_id3 (HEAD -> master)Author: testDate: Thu Aug 20 16:28:45 2020 +0800 第二次批改README文件commit commit_id2Author: testDate: Thu Aug 20 16:28:19 2020 +0800 第一次批改README文件commit commit_id1Author: testDate: Thu Aug 20 16:26:59 2020 +080 初始化我的项目
4、将本地批改同步到近程仓库
命令:git push origin HEAD --force
将本地批改强行同步到近程仓库,使得近程仓库和本地仓库保持一致!
整体流程如下:
git loggit reset commit_id3批改代码git add .git commit -m '第三次批改README文件-更新谬误后提交'git push origin HEAD --force
洋仔:好了,小明,你的问题完满解决了小明:哦吼,然而我还有一个问题: 如果我想要不保留回滚commit的批改,间接删除掉批改!该怎么解决呢?
洋仔:简略~ 咱们整体看一下 git reset 命令
后悔药-git reset
在进行上面的解说是,还是先假如有这么一个提交链:
commit_id1 --> commit_id2 --> commit_id3 --> commit_id4
git reset <param> commit_id2:
reset是将HEAD从新定位到commit_id2
上,对于commit_id3 和 commit_id4 和本地以后的批改,对于不同的参数param,会有不同的解决;
reset命令有三种解决模式:
- --soft:保留commit批改,将批改存储到index中;也就是说git add后的区域
- --mixed:保留commit批改,将批改存储到本地工作区域中;也就是说git add前的区域
- --hard:删除commit批改,慎用!
git reset --soft
回滚commit_id前的所有提交,不删除批改:
git reset --soft commit_id
重设head,不动index,所以成果是commit_id之后的commit批改全副在index中
将id3 和 id4的批改放到index区(暂存区),也就是add后文件寄存的区域,本地以后的批改保留
git reset --mixed
回滚commit_id前的所有提交,不删除批改:git reset commit_id
等同于 git reset --mixed commit_id
与 下述的 git reset --hard commit_id成果不同
重设head 和 index,不重设work tree,成果就是commit_id之前的批改,全副在work tree中,为还未add的状态
将id3 和 id4 的所有批改放到本地工作区中,本地以后的批改保留
git reset --hard
回滚commit_id前的所有提交,将批改全副删除:git reset --hard commit_id
重设head、index、work tree,也就是说将以后我的项目的状态复原到commit_id的状态,其余的全副删除(蕴含commit_id后的提交和本地还未提交的批改)
慎用!!
后悔药-git revert
小明:原来git reset这么弱小呀! 然而我这还有个问题:
如果想要只操作批改两头的一个commit,不对其余的commit产生影响; 也就是相似于咱们只批改commit_id2,而对commit_id3 和 commit_id4无影响,该怎么解决呢?
洋仔:(这么多问题,幸好我懂,要不这次就丢大了。。) 简略! git revert 命令!
实用场景: 在我的项目开发中,忽然发现在前几次的提交中,有一次提交中蕴含一个bug; 当然咱们能够进行一个新的批改,而后再提交一次; 然而,不优雅哈哈; 咱们能够间接重做有bug的commit~
为什么不间接去再增加一个commit呢? git revert是用于“反做”某一个版本,以达到撤销该版本的批改的目标。
比方,咱们commit了三个版本(版本一、版本二、 版本三),忽然发现版本二不行(如:有bug),想要撤销版本二,但又不想影响撤销版本三的提交,就能够用 git revert 命令来反做版本二,生成新的版本四,这个版本四里会保留版本三的货色,但撤销了版本二的货色;
在revert命令中罕用的就两个:
- git revert -e <commit_id>:重做指定commit的提交信息
- git revert -n <commit_id>:重做执行commit的代码批改
git revert -e
重做commit_id的提交信息,生成为一个新的new_commit_idgit revert -e commit_id
git revert -n
重做commit_id的提交git revert -n commit_id
将commit_id中批改,放到index区,咱们能够对他从新做批改并从新提交
revert vs reset
- git revert是用一次新的commit来回滚之前的commit,此次提交之前的commit都会被保留不动;
- git reset是回到某次提交,提交及之前的commit都会被保留,然而此commit id之后的批改都会被删除或放回工作区期待下一次提交;
小明:还有这种操作,能够间接独自操作提交过程中的某一个commit! 太棒了!
后悔药-git checkout
小明:还有最初一个问题:如果我在一次开发中,发现某个文件批改谬误了,想要将文件复原到刚pull代码时的状态怎么办呢?
洋仔:简略! 看git checkout解决这个问题!
咱们晓得应用git checkout
能够
git checkout <branch_name>
切换分支git checkout -b <branch_bame>
创立分支等操作
它还有回滚指定文件的批改的性能
命令:git checkout -- <file_name>
上述语句的作用,就是将file_name的本地工作区的批改全副撤销,有两种状况:
- 如果file_name在commit后没有add过这个文件,则撤销到版本库中的状态
- 如果file_name在commit后add过这个文件,则撤销到暂存区的状态,也就是add后的状态
总之,就是让指定的文件回滚到最近的一次git add
或者 git commit
时的状态!
小明:太棒了,当前再也不怕提错代码了!
总结
上述,咱们介绍了git reset git revert git checkout 在版本回滚、重做、撤销批改方面的作用;
能够利用到工作中对 误操作、不满足要求、不满足志愿的commit记录的重做和批改;
不必慌谬误的commit了,撒花~