一、回溯概述

  • Git的另一特征便是可以灵活操作历史版本。借助分散仓库的优势, 可以在不影响其他仓库的前提下对历史版本进行操作

二、回溯命令

  • 命令如下:
git reset --hard [hashValue]
  • 回溯时,只要提供目标时间点的哈希值,就可以完全恢复至该时间点的状态

演示案例

  • 我们接着前一篇文章的演示案例:https://blog.csdn.net/qq_41453285/article/details/106127078。现在我们想要回溯到创建feature-A分支之前的状态
  • 第一步:先查看一下日志,然后查看到创建feature-A分支之前的状态的哈希值为“e48412e3e7247e968cf85315ffcd02a9bafce031”
  • 第二步:回溯之前查看一下当前处于master分支下,并且README.md文件的内容如下:
  • 第三步:使用命令进行回溯,并且README.md文件的内容也回到了之前的样子
 git reset --hard e48412e3e7247e968cf85315ffcd02a9bafce031

三、解决合并冲突

  • 现在我们创建一个新的分支B,然后再将master回溯到feature-A 分支合并后的状态(“推进历史”),然后将master与分支B进行合并,但是合并的时候README.md文件的内容会不一致,所以会产生冲突

①创建分支B

  • 接着上面的演示案例,我们创建一个新的分支B,并且切换到分支B下:
git checkout -b fix-B

  • 然后我们修改分支B下的README.md文件,内容如下:
  • 之后我们对分支B进行添加、提交:
git add README.md
git commit -m "Fix B"

  • 现在的状态如下图所示:
  • 接下来,我们的目标是:在文章的最开始,我们将master回溯到了创建feature-A分支之前的状态,现在我们又想要回溯到“主干分支合并feature-A分支的修改后”的状态,然后再与fix-B分支进行合并

②推进至 feature-A 分支合并后的状态

  • 现在我们想要先恢复到fearure-A分支合并后的状态,类似于“推进历史”的概念
  • git log命令只能查看以当前状态为终点的历史日志。此处我们使用git reflog命令查看当前仓库的操作日志,在日志中找出回溯历史之前的哈希值,通过git reset –hard命令恢复到回溯历史前的状态
  • 首先,执行下面的命令,查看当前仓库执行过的操作日志:
git reflog

  • 在上图,我们可以看到commit、checkout、reset、merge等git命令的执行记录。只要不进行git的GC(Garbage Collection,垃圾回收),就可以通过日志随意调取近期的历史状态,然后恢复到指定的状态。如果开发者错误执行了git操作,也可以利用git reflog命令恢复到原先的状态
  • 在上图中,第4行表示feature-A特性分支合并后的状态,对应的哈希值为“9a1b278”(备注:此处的哈希值为什么这么短,因为哈希值只要输入4位以上就可以了,所有此处显示的比较短)
  • 在恢复之前,我们先切换到master分支下,然后查看一下README.md文件的内容
  • 现在我们将HEAD、暂存区、工作树恢复到feature-A特性分支合并后的状态,并且文件的内容也恢复到那个时间点上了
git reset --hard 9a1b278

  • 现在的状态如下所示,master恢复到“feature-A特性分支合并后的状态”,并且还没有与分支B进行合并

③将master与fix-B合并,会产生冲突

  • 在合并之前,我们切换到fix-B分支下,查看一下README.md文件的内容:
  • 然后再切换到master分支下,查看一下README.md文件的内容:
  • 通过上面可以看到,在两个分支之下,两个文件的内容不一致
  • 现在我们在master分支下,然后想要与fix-B分支进行合并:
git merge --no-ff fix-B

  • 上图合并的时候可以看到,系统告诉我们README.md文件发生了冲突(Conflict),feature-A 分支更改的部分与本次想要合 并的 fix-B 分支更改的部分发生了冲突,不解决冲突就无法完成合并

④解决冲突

  • 现在我们在master分支下查看README.md文件,发现其内容变成了如下所示的样子:
    • ========以上的部分是当前HEAD的内容
    • ========以下的部分是要合并的fix-B分支中的内容
  • 产生冲突之后,我们也不能切换到其他分支下了
  • 现在我们在master分支下修改README.md文件,将其内容修改为下面的样子(在实际开发中,往往需要删除其中之一)
  • 修改之后,我们执行下面的命令进行添加、提交:
  • 无冲突之后,现在我们可以切换到任意分支下了,并且每个分支的内容都彼此独立

四、修改提交信息

  • 要修改上一条提交信息,可以使用下面的命令
git commit --amend

演示案例

  • 接着“三”中的演示案例,在上面我们解决合并冲突之后,提交时备注的信息为“README.md”,如下图所示(图片取自上面的演示案例)
  • 并且在日志中也可以看到提交信息
  • 现在我们想要修改上一条提交信息,那么可以输入下面的命令
git commit --amend
  • 执行上面的命令之后,编辑器就会启动,然后来到下图所示的样子
  • 编辑器中显示的内容如上所示,其中包含之前的提交信息。现在我们将提交信息的部分修改为 Merge branch ‘fix-B’,然后保存文件,关闭编辑器
  • 现在我们再次查看日志记录,可以看到提交日志中的相应内容也已经被修改了

五、压缩历史(git rebase)

  • 应用场景之一:在合并特性分支之前,如果发现已提交的内容中有些许拼写错误等, 不妨提交一个修改,然后将这个修改包含到前一个提交之中,压缩成一 个历史记录
  • 这是个会经常用到的技巧,让我们来实际操作体会一下

①创建feature-C分支

  • 我们来创建一个feature-C分支,通知切换到该分支下
git checkout -b feature-C

 

  • 然后我们修改README.md文件,在最后一行加入“faeture-C”,故意将“feature”单词拼写错误
  • 然后进行添加、提交
git commit -am "Add feature-C"

②修正拼写错误

  • 接着上面,我们发现错误之后,打开README.md文件,将单词重新修改正确
  • 然后查看一下差别
git diff

  • 修改之后,我们再次进行一次提交,此处备注信息为“Fix typo”
git commit -am "Fix typo"

③压缩/更改历史

  • 在①和②中我们总共提交了两次,所以在历史记录中这两条都被记录下来,但是这两条是重复的,第一条其实不需要了,因此下面我们将第一次提交和第二次提交进行压缩
  • 首先输入下面的命令,下面的命令选定当前分支中包含 HEAD(最新提交)在内的两个最新历史记录为对象
git rebase -i HEAD~2
  • 输入上面的命令之后会打开编辑器
  • 根据上面的提示,我们想要将“277caf1”的历史记录压缩到“416a6ca”的“Add feature-C”记录中。更改的方式为:将“277caf1”前面的“pick”改写为“fixup”,然后保存退出编辑器
  • 保存退出之后,内容如上所示,可以看到合并成功
  • 然后查看一下日志,可以看到“Add feature-C”的哈希值已经不是“416a6ca….”,这证明已经修改了
  • 这样一来,Fix typo就从历史中被抹去,也就相当于 Add feature-C 中从来没有出现过拼写错误。这算是一种良性的历史改写
  • 接下来(此步骤可选):现在我们切换到master分支下,将fearture-C分支与master进行合并

本文地址:https://blog.csdn.net/qq_41453285/article/details/106144132