当前位置: 首页 > news >正文

Git——修改历史记录详解

目录

  • Git
    • 1、修改历史信息
      • 1.1、启动互动模式
      • 1.2、修改Commit信息的影响
      • 1.3、取消Rebase
    • 2、多个Commit合并位一个Commit
    • 3、一个Commit拆解成多个Commit
    • 4、在某些Commit之间插入新的Commit
    • 5、删除Commit
    • 6、调整Commit的顺序
    • 7、Revert指令
      • 7.1、取消Commit
      • 7.2、取消Revert
        • 1、再开一个Revert
        • 2、直接使用Reset
    • 8、Reset、Rebase和Revert区别

Git

1、修改历史信息

要修改历史信息,可使用--amend参数来修改最后一次Commit的信息,但这仅限于最后一次,如果要改动其他更早的信息,就得使用其他方法了。

前面介绍过的git rebase指令有一种强大的互动模式,接下来的几节内容都是介绍怎样使用这种模式来改动过去的历史记录。首先看一下当前的状况:

git log --oneline

在这里插入图片描述

1.1、启动互动模式

下面使用Rebase指令整理一下:

git rebase -i 4cb958a

-i参数是指要进入Rebase指令的“互动模式”,而后面的4cb958a是指这次Rebase指令的应用范围为“从现在到4cb958a这个Commit”,也就是最开始的那个Commit。这个指令会弹出一个Vim编辑器:
在这里插入图片描述

这里需注意以下两点:

  1. 上面的顺序与git log指令的结果是相反的,但在SourceTree界面中是一样的。
  2. 上面的pick是指“保留这次的Commit,不做改动”,其他指令稍后会介绍。

修改指令,选取两行把pick改成reword(r):
在这里插入图片描述

存档并离开之后,会立即弹出另一个Vim编辑器画面:
在这里插入图片描述

修改第一个Commit信息,然后保存:
在这里插入图片描述

修改第二个Commit信息,然后保存:
在这里插入图片描述

再次查看历史记录:
在这里插入图片描述

1.2、修改Commit信息的影响

看起来好像只是改了信息,只涉及单纯的文字变动,其实没有那么简单。如果仔细看,就会发现那两次Commit的SHA-1值都变了,这两次的Commit已经是全新的Commit对象了。

进行Rebase时,Commit对象并不是剪切、粘贴而已,因为要接的前一个Commit不同(其实时间也不同),所以会重新计算并做出一个新的Commit对象。

这里也是一样,看起来只是改字,但因为Commit对象的信息也会影响SHA-1的计算,所以Git会做出新的Commit对象来替代原来的Commit对象。

不止这样,因为这两个Commit对象被换掉了,在它之后的Commit因为前面的历史信息被改了,所以后面整串的Commit全部都重做新的Commit对象来替代旧的Commit对象。

1.3、取消Rebase

如果想要取消这次的Rebase,只需这样做:

git reset ORIG_HEAD --hard

2、多个Commit合并位一个Commit

新增两个文件并分两次提交:

echo "111" > 1.txt
echo "222" > 2.txt
git add .
git commit 1.txt -m "add 1"
git commit 2.txt -m "add 2"

查看记录:
在这里插入图片描述

如果把这2个Commit合并为一个,就会让Commit看起来更简洁。可以使用互动模式的Rebase来处理:

git rebase -i d249c0f

在这里插入图片描述

这里使用squash指令,把上面的内容改为:

在这里插入图片描述

上面的改动表示cc722b0这个Commit会和前一个05b8f3eCommit合并在一起。

随后修改合并后的Commit信息:
在这里插入图片描述

再次查看记录,合并成功:在这里插入图片描述

3、一个Commit拆解成多个Commit

继续使用上文中的案例,目的是把51422de这个Commit拆分为2个Commit,每个Commit只有一个文件即可。

git rebase -i d249c0f

在这里插入图片描述

这次把要拆解的那个Commit的pick改成edit:
在这里插入图片描述

保存后,Rebase在执行到51422de这个Commit时就会停下来:

在这里插入图片描述

这时,因为要把当前这个Commit拆解成两个Commit,所以要使用Reset指令:

git reset HEAD^

然后查看一下状态:
在这里插入图片描述

可以看到,1.txt和2.txt都被拆解出来放在工作目录中,且处于Untracked状态。还记得怎么Commit文件吗?就是用add + commit二段式指令:

git add .
git commit 1.txt -m "add 1"
git commit 2.txt -m "add 2"

最后执行

git rebase --continue

以完成rebase交互。

查看记录,完成了拆分:
在这里插入图片描述

4、在某些Commit之间插入新的Commit

还是使用上面案例,在(69204dc)add 2和(e061b15)add 1之间插入一个Commit。

git rebase -i d249c0f

在这里插入图片描述

处于Rebase状态的Commit列表与平常看到的记录是相反的,所以如果想在某两个Commit之间再增加Commit,要注意停下来的那个点是不是正确的点。例如,要加在add 2和add 1之间增加Commit,需要停在add 1上:

在这里插入图片描述

保存后,Rebase操作执行,停在add 1的Commit上:
在这里插入图片描述

此时,就可以新增Commit了:

echo "1.5" > 1.5.txt
git add 1.5.txt
git commit 1.5.txt -m "add 1.5"

随后继续执行Rebase操作:

git rebase --continue

查看记录,插入Commit成功:

在这里插入图片描述

5、删除Commit

继续使用上述案例,删除掉add 1.5这个Commit。

要删除Commit很简单,在Rebase的过程中,把原来的pick改成drop,甚至直接将其删掉也可以。

git rebase -i d249c0f

在这里插入图片描述

如果想删掉add 1.5,可以把该行的pick改成drop,或者直接删除掉该行:
在这里插入图片描述

存档、离开后便会开始进行Rebase。然后查看记录,删除成功:
在这里插入图片描述

6、调整Commit的顺序

继续使用上述案例,假设先在要互换add 1和add 2这两个Commit的顺序。

git rebase -i d249c0f

在这里插入图片描述

只需要互换两个记录的顺序即可:
在这里插入图片描述

存档、离开后,Rebase就会继续做它的工作。然后查看记录,顺序已经调整成功:

在这里插入图片描述

7、Revert指令

7.1、取消Commit

继续使用上文案例,假设要取消最后的add 1这个Commit。

git revert HEAD --no-edit

在这里插入图片描述

这样就把最后一次Commit的内容删掉了。虽然文件不见了,但是Commit增加了。

Revert指令是“再做一个新的Commit,来取消你不要的Commit”,所以Commit的数量才会增加。

7.2、取消Revert

如果做出来的Revert不想要了,可用以下几种方式来处理:

1、再开一个Revert

可以再开一个新的Revert,来Revert刚才那个Revert:

git revert HEAD --no-edit

在这里插入图片描述

刚刚被删掉的1.txt又出现了,这样Commit又变多了。

2、直接使用Reset

如果要“砍掉”这个Revert,只需直接使用Reset指令:

git reset HEAD^ --hard

8、Reset、Rebase和Revert区别

指令修改历史记录说明
Reset把当前状态设置成某个指定Commit的状态,通常适用于尚未推出去的Commit
Rebase不管是新增、改动、删除Commit,还是用来整理、编辑还没有推出去的Commit,都相当方便,但通常只适用于尚未推出去的Commit
Revert新增一个Commit来反转(或说取消)另一个Commit的内容,原来的Commit依旧会保留在历史记录中。虽然会因此而增加Commit数量,但通常比较适用于已经推出去的Commit,或者不允许使用Reset或Rebase来修改历史记录指令的情景

相关文章:

  • Hadoop学习3:问题解决
  • PHP 生成图片
  • OPC UA 服务器的Web访问
  • 面向对象技术
  • 软考76-上午题-【面向对象技术3-设计模式】-创建型设计模式01
  • ​【已解决】npm install​卡主不动的情况
  • Fair Data Exchange:区块链实现的原子式公平数据交换
  • HTML万字学习总结
  • 【Web开发】CSS教学(超详细,满满的干货)
  • HTML本地离线缓存?
  • 中国城市统计年鉴、中国县域统计年鉴、中国财政统计年鉴、中国税务统计年鉴、中国科技统计年鉴、中国卫生统计年鉴​
  • 【首次抽奖】16G、32G免费送!云服务器选购推荐 京东云 阿里云 腾讯云对比 幻兽帕鲁 雾锁王国 省钱学生党
  • 读书笔记--数据建模与设计的总结感悟
  • OpenvSwitch VXLAN 隧道实验
  • 指挥航空公司架次与延误率占比
  • 收藏网友的 源程序下载网
  • “大数据应用场景”之隔壁老王(连载四)
  • Cumulo 的 ClojureScript 模块已经成型
  • JavaScript创建对象的四种方式
  • java概述
  • js正则,这点儿就够用了
  • MySQL-事务管理(基础)
  • XML已死 ?
  • 分享几个不错的工具
  • 给第三方使用接口的 URL 签名实现
  • 前端之React实战:创建跨平台的项目架构
  • 浅谈Golang中select的用法
  • 如何借助 NoSQL 提高 JPA 应用性能
  • 译自由幺半群
  • 最近的计划
  • Hibernate主键生成策略及选择
  • LevelDB 入门 —— 全面了解 LevelDB 的功能特性
  • #、%和$符号在OGNL表达式中经常出现
  • (4)Elastix图像配准:3D图像
  • (NSDate) 时间 (time )比较
  • (附源码)springboot太原学院贫困生申请管理系统 毕业设计 101517
  • (附源码)ssm高校运动会管理系统 毕业设计 020419
  • (转)Oracle存储过程编写经验和优化措施
  • (转)程序员疫苗:代码注入
  • .cfg\.dat\.mak(持续补充)
  • .form文件_一篇文章学会文件上传
  • .NET Core Web APi类库如何内嵌运行?
  • .net oracle 连接超时_Mysql连接数据库异常汇总【必收藏】
  • .NET Remoting Basic(10)-创建不同宿主的客户端与服务器端
  • .NET 材料检测系统崩溃分析
  • .net 逐行读取大文本文件_如何使用 Java 灵活读取 Excel 内容 ?
  • .net和php怎么连接,php和apache之间如何连接
  • .net获取当前url各种属性(文件名、参数、域名 等)的方法
  • .NET建议使用的大小写命名原则
  • .Net转前端开发-启航篇,如何定制博客园主题
  • @ConditionalOnProperty注解使用说明
  • [.net]官方水晶报表的使用以演示下载
  • [1181]linux两台服务器之间传输文件和文件夹
  • [ArcPy百科]第三节: Geometry信息中的空间参考解析
  • [C]整形提升(转载)