你知道Git版本控制系统中都有哪些“后悔药”吗?git
本文经过案例讲解
git reset 、 git revert 、 git checkout
在版本控制中的做用;fetch
小明同窗做为新人加入到一个新的项目组中作开发,在项目的迭代开发中,小明勤勤恳恳的写代码,直到有一次...spa
小明:完了,完蛋了.net
洋仔:怎么了,一惊一乍的版本控制
小明:我把错误代码用git commit后还push到线上代码库了! 这可怎么办!code
洋仔:莫慌,git有“后悔药”!xml
洋仔:容我给你慢慢道来。 可是咱们要先知道一些git的基础知识,你才能更好的理解git命令的做用blog
git将项目的存储分为4部分,每部分有本身做用,开发
见下图:rem
Workspace
:工做区(当前用户操做修改的区域)Index / Stage
:暂存区 (add后的区域)Repository
:仓库区或本地仓库(commit后的区域)Remote
:远程仓库(push后的区域)总体过程能够简述为:
add
–>暂存区–>commit
–>本地仓库区–>push
–>远程仓库区fetch
–>使用refs\remotes下对应分支文件记录远程分支末端commit_id 和 本地仓库区 -->merge
–>工做区pull
–>使用refs\remotes下对应分支文件记录远程分支末端commit_id and 本地仓库区 and 工做区具体的git的组成部分和概念命令,请移步下述两个博客:
假设项目存在这么一个提交记录:
$ git log commit commit_id4 (HEAD -> master) Author: test Date: Thu Aug 20 16:28:45 2020 +0800 第三次修改README文件 commit commit_id3 (HEAD -> master) Author: test Date: Thu Aug 20 16:28:45 2020 +0800 第二次修改README文件 commit commit_id2 Author: test Date: Thu Aug 20 16:28:19 2020 +0800 第一次修改README文件 commit commit_id1 Author: test Date: Thu Aug 20 16:26:59 2020 +080 初始化项目
提交顺序为:commit_id1
--> commit_id2
--> commit_id3
--> commit_id4
注意:在git中每次的commit都有一个commit id惟一标识当前的提交!
下面,咱们先来解决小明的这个问题,使用git reset
便可完美解决~
洋仔:小明,你的这个就能够用git reset 这个命令来完美的搞定,下面咱们看一下如何解决
一、获取当前提交的commit id
命令:git log
获取到当前项目分支下的全部commit记录;
假设上述小明提交错误的commit id为commit id:commit_id4
这一次提交;
他的上一次提交就是commit id:commit_id3
,咱们要将修改回滚到commit_id3
的时刻!
小明:我想要把我刚才 commit的修改保留下来,我修改的代码不能给我删除掉呀!
洋仔:没问题
二、将某个commit id前的commit清除,并保留修改的代码
命令:git reset <commit_id>
当前场景下就是:git reset commit_id3
将指定commit_id后的全部提交,都去除,并保留修改的代码在本地的区域,也就是Workspace
中
小明:啊哈,这样的话我就能够把错误代码修改后再提交了; 可是我已经push到线上仓库的数据怎么办呢?
洋仔:别急,有办法~
三、修改代码完成后,将修改好的代码add到暂存区,并提交到本地仓库中
命令:git add <file_name>
and git commit
当前场景下:git add .
and git commit
将最新修改后的代码commit
则提交后的提交记录假设以下: 能够看到,咱们错误提交的commit_id4
提交记录消失,取而代之的是咱们更新代码后提交的记录commit_id5
; 这样就完成了本地的代码修改和更新
$ git log commit commit_id5 (HEAD -> master) Author: test Date: Thu Aug 20 16:28:45 2020 +0800 第三次修改README文件-更新错误后提交 commit commit_id3 (HEAD -> master) Author: test Date: Thu Aug 20 16:28:45 2020 +0800 第二次修改README文件 commit commit_id2 Author: test Date: Thu Aug 20 16:28:19 2020 +0800 第一次修改README文件 commit commit_id1 Author: test Date: Thu Aug 20 16:26:59 2020 +080 初始化项目
四、将本地修改同步到远程仓库
命令:git push origin HEAD --force
将本地修改强行同步到远程仓库,使得远程仓库和本地仓库保持一致!
总体流程以下:
git log git reset commit_id3 修改代码 git add . git commit -m '第三次修改README文件-更新错误后提交' git push origin HEAD --force
洋仔:好了,小明,你的问题完美解决了
小明:哦吼,可是我还有一个问题: 若是我想要不保留回滚commit的修改,直接删除掉修改!该怎么处理呢?
洋仔:简单~ 咱们总体看一下 git reset 命令
在进行下面的讲解是,仍是先假设有这么一个提交链:
commit_id1 --> commit_id2 --> commit_id3 --> commit_id4
git reset commit_id2:
reset是将HEAD从新定位到commit_id2
上,对于commit_id3 和 commit_id4 和本地当前的修改,对于不一样的参数param,会有不一样的处理;
reset命令有三种处理模式:
回滚commit_id前的全部提交,不删除修改:
git reset --soft commit_id
重设head,不动index,因此效果是commit_id以后的commit修改所有在index中
将id3 和 id4的修改放到index区(暂存区),也就是add后文件存放的区域,本地当前的修改保留
回滚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 的全部修改放到本地工做区中,本地当前的修改保留
回滚commit_id前的全部提交,将修改所有删除:
git reset --hard commit_id
重设head、index、work tree,也就是说将当前项目的状态恢复到commit_id的状态,其他的所有删除(包含commit_id后的提交和本地还未提交的修改)
慎用!!
小明:原来git reset这么强大呀! 可是我这还有个问题:
若是想要只操做修改中间的一个commit,不对其余的commit产生影响; 也就是相似于咱们只修改commit_id2,而对commit_id3 和 commit_id4无影响,该怎么处理呢?
洋仔:(这么多问题,幸好我懂,要不此次就丢大了。。) 简单! git revert 命令!
适用场景: 在项目开发中,忽然发如今前几回的提交中,有一次提交中包含一个bug; 固然咱们能够进行一个新的修改,而后再提交一次; 可是,不优雅哈哈; 咱们能够直接重作有bug的commit~
为何不直接去再添加一个commit呢? git revert是用于“反作”某一个版本,以达到撤销该版本的修改的目的。
好比,咱们commit了三个版本(版本1、版本2、 版本三),忽然发现版本二不行(如:有bug),想要撤销版本二,但又不想影响撤销版本三的提交,就能够用 git revert 命令来反作版本二,生成新的版本四,这个版本四里会保留版本三的东西,但撤销了版本二的东西;
在revert命令中经常使用的就两个:
重作commit_id的提交信息,生成为一个新的new_commit_id
git revert -e commit_id
重作commit_id的提交
git revert -n commit_id
将commit_id中修改,放到index区,咱们能够对他从新作修改并从新提交
小明:还有这种操做,能够直接单独操做提交过程当中的某一个commit! 太棒了!
小明:还有最后一个问题:
若是我在一次开发中,发现某个文件修改错误了,想要将文件恢复到刚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记录的重作和修改;