你知道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–>使用refs\remotes下对应分支文件记录远程分支末端commit_id 和 本地仓库区 -->merge–>工作区

  • 远程仓库区–>pull–>使用refs\remotes下对应分支文件记录远程分支末端commit_id and 本地仓库区 and 工作区

具体的git的组成部分和概念命令,请移步下述两个博客(超链接):

Git技术干货!工作中Git的使用实践和常用命令合集!

Git - 使用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 这个命令来完美的搞定,下面我们看一下如何解决

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 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初始化项目

4、将本地修改同步到远程仓库

命令: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 命令

后悔药-git reset

在进行下面的讲解时,还是先假设有这么一个提交链:

commit_id1 --> commit_id2 --> commit_id3 --> commit_id4

git resetcommit_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了,撒花~

IT技术分享社区

个人博客网站:https://programmerblog.xyz

文章推荐程序员效率:画流程图常用的工具程序员效率:整理常用的在线笔记软件远程办公:常用的远程协助软件,你都知道吗?51单片机程序下载、ISP及串口基础知识硬件:断路器、接触器、继电器基础知识

没想到,Git居然有3种“后悔药”!相关推荐

  1. 港中文大学计算机科学面试吗,听说过香港有需要面试的专业,但没想到这些居然还要笔试??...

    原标题:听说过香港有需要面试的专业,但没想到这些居然还要笔试?? Photo byRobert BakeronUnsplash 听说过香港有需要面试的专业,但没想到这些居然还要笔试?? 今天Cecil ...

  2. ps4插html屏幕不亮光,万万没想到,居然是这个!PS4黑屏的原因终于找到了!

    往往最容易获得的最容易忽视 原本想着换了新显示器就可以安逸的打机了,结果新的问题却出现了.自从PS4 Pro原装线被人"借走"后,只能用一根装机时的"赠品"顶着 ...

  3. 万万没想到,线程居然被饿死了!

    我们在构建线程池的时候可以构建单个线程的线程池和多个线程的线程池. 那么线程池使用不当可不可能产生死锁呢?我们知道死锁是循环争夺资源而产生的.线程池中的线程也是资源的一种,那么如果对线程池中的线程进行 ...

  4. char转成string_真没想到,一个小小的String居然还有这么多窍门?

    推荐学习 公司来了位阿里P8大神,看完他的手写"Kafka笔记",万分膜拜 牛掰!"基础-中级-高级"Java程序员面试集结,看完献出我的膝盖 真没想到,一个小 ...

  5. 远程抄表 本地服务器,没想到实现远程抄表真正原因居然是它

    原标题:没想到实现远程抄表真正原因居然是它 现在都是远程抄表系统,远程抄表可以杜绝人工抄表的错误和麻烦,可以让用户先付费再用电,这样管理中心资金比较容易收回,不会发生有资金断流的现象,那么远程抄表到底 ...

  6. Git 提交代码之后的几种后悔药

    1. 前言 写代码都会犯错误,不小心提交了一个错误我该怎么办?提交的描述信息我该怎么办?如果你也遇到这个问题,那么今天胖哥分享的这篇文章将非常适合你. DD自研的沪牌代拍业务,点击直达 2. Comm ...

  7. 关于“如何破坏单例“我说了好几种方式,面试官却说:我其实随便问问,没想到你真会

    单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.是一种创建型设计模式.他的定义为:保证一个类仅有一个实例,并提供一个访问它的全局访问点. 单例模式一般体现在类声明中 ...

  8. 关于如何破坏单例我说了好几种方式,面试官却说:我其实随便问问,没想到你真会...

    单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.是一种创建型设计模式.他的定义为:保证一个类仅有一个实例,并提供一个访问它的全局访问点. 单例模式一般体现在类声明中 ...

  9. mysql double 转 字符串_没想到!在MySQL数据库中的数据有这三种类型!

    MySQL数据库是一个或多个数据列构成二维表,它的每一种数据列都有特定类型,而类型决定MySQL是怎么看待该列数据,如果把整型数值存放到字符类型的列中,MySQL则会把它当成字符串来处理. MySQL ...

最新文章

  1. python内置函数可以返回列表元组_Python内置函数()可以返回列表、元组、字典、集合、字符串以及range对象中元素个数....
  2. 【Java 虚拟机原理】栈帧 | 局部变量表 | 操作数栈 | 方法出口 | JVM 指令逐条解析
  3. RxJava 教程第一部分:入门之 关键的类
  4. 始化mysql系统库_安装和初始化mysql-8.0.11-winx64
  5. 计算机小技巧7,大神也未必知道的7个电脑小技巧,你会吗?
  6. 如何使用SPSS进行相关性分析
  7. NSIS 第一个安装程序
  8. html5图片自动轮播纯代码,HTML5的自定义data-*实现图片切换或者轮播(代码实例)...
  9. sis地址发布器_Go 1.15 正式发布:看看都有哪些值得关注的变化
  10. 一文彻底搞懂Mybatis系列(二)之mybatis事务管理机制深度剖析
  11. JavaSE实战项目:飞翔的小鸟(完整版)
  12. Docker、Docker file、Docker-compose 详解
  13. 视频基础知识—720P/1080i/1080P
  14. 前端第一阶段-11(HTML之flex弹性)
  15. Mac系统下docker容器无法使用--net host共享宿主机端口的解决方案
  16. 27. hall霍尔传感器
  17. Google Adsense(谷歌网站联盟)广告申请指南
  18. (转)【如何快速的开发一个完整的iOS直播app】(原理篇)
  19. 学习前段HTML+CSS+JS的过程(一)
  20. 涨姿势!国外程序员搞副业的 10 大方式

热门文章

  1. 在Ubuntu 16.04 上安装和卸载matlab 2018b(Install and uninstall matlab 2018b on ubuntu)
  2. halcon2D Metrology测量算子,卡尺测量算子,持续更新
  3. MoveAbsJ在使用时和MOVEJ有什么区别
  4. Basler相机SDK相关问题收集与知识汇总
  5. c++显式加载dll并使用DLL的类
  6. 最近的一些校招试题摘录
  7. python语言是机器语言_Python解释器:源代码--字节码--机器语言
  8. $2019$ 暑期刷题记录 $2$(基本算法专题)
  9. 2018-07-10 为Chrome和火狐浏览器编写扩展
  10. ansible模块介绍