你一定遇到过,一个很久没修改过的功能,莫名其妙的出现了问题?肉眼查代码、屡逻辑完全找不到问题点?前两天还好好的功能,怎么这个今天就不行了?这两天改动了这么多代码,到底是那一次改动引发的 Bug?

这样非崩溃的 Bug,有时候想要排查出问题,并不是一件容易的事情。我想,这个时候你会需要 git bisect !

一、git bisect 基础使用

git bisect 是 Git 提供的一种 二分法 的调试工具,它可以按照我们选定的提交,进行二分分割,快速定位出出错的提交。来帮我们缩小最小改动的代码,从而快速定位问题。

git bisect 其实很简单,主要是基于几个基本命令:

  • git bisect start:准备进行 bisect debug。
  • git bisect good:标记一个提交为 "good"。
  • git bisect bad:标记一个提交为 “bad”。
  • git bisect reset:退出 bisect debug 的状态。

git bisect 涉及到的命令,非常的清晰简单,下面举个实际的例子,结合上面的解释,就更清晰了。

二、git bisect 工作流

我自己生造出 6 个 commit,然后使用 git log 看看我的提交记录。

这里假设我正常开发的阶段,到 v6 提交的时候,突然发现有个 Bug ,无法定位到问题,但是能明确的知道,在 v1 提交阶段,并没有这个 Bug。

那么,在这样的情况下,v6 就是一个有问题的版本,而 v1 则是一个好的版本,我们就可以借助 git bisect 来进行二分超找定位问题来自哪个提交。

还记得刚才的命令吗?

我们先用 git bisect start 标记开始 bisect debug ,然后使用 git bisect goodgit bisect bad 分别标记出正确的和错误的提交。

每个提交,都有一个针对这个提交唯一的 SHA-1 值,因为太长不方便输入和阅读,这里可以直接使用前几位作为简写。

当标记处正确的和错误的提交之后,git bisect 立刻就可以帮我们定位出中间提交 v3

现在 HEAD 就已经指向了 v3 提交的代码了,这个可以使用 git status 查看当前的状态。

所以我们可以基于 v3 版本的代码,直接运行项目,测试看该提交是否有问题。

经过测试之后,发现 v3 的提交代码版本,并没有复现 Bug,那我们就可以缩小错误提交的范围,大概落在了 v4v5v6 之间。

此时,我们只需要使用 git good 标记 v3 版本是正确的。

标记好 v3good 之后,立刻又会进行一次二分,此次标记的为中间提交 v5

经过对 v5 提交的版本代码,进行测试之后发现,它是有问题的。我们继续使用 git bisect bad 对它进行标记。

v5 有问题的时候,现在只中间一个 v4 版本,所以会立刻指向 v4 提交。

我们继续对 v4 版本的代码进行测试,发现 v4 版本也有问题,继续标记它为 bad

此时就很明确了,出错的提交就是 v4,而 Git 也直接帮我们指出来出错的提交。

虽然这里定位到,出错的提交就是 v4 的问题,我们只需要仔细阅读 v4 提交的代码,然后定位出问题代码,就达到了我们的目的。但是我们并不应该在 v4 提交上直接修改 Bug,我们应该退出 bisect debug 状态,在最新的提交版本上进行修改,这里使用 git bisect reset 退出,再进行修改即可。

到这里,就是 git bisect 的完整工作流程。

三、bisect的后悔药

对提交进行 goodbad 的标记,都是人为来进行的,难免有出错的情况。而提交比较少的时候,大不了就是 reset 之后,重头来过。

但是如果有几十个提交,再从头进行一次 bisect 就比较麻烦了。Git 考虑到这一点,已经为我们配好了后悔药。

想要擦除之前的标记状态,就涉及到一个命令:

  • git bisect replay:重置到某个状态。

replay 需要制定一个回退的点,这个点是需要使用 git bisect log > log.txt 输出的 Log 文件, 我们需要通过修改这个 Log 文件,来确定回退的点。

举个例子,我们使用 log 命令,输出一个 log.txt 文件。

可以看到,这个 log.txt 文件,记录了我们刚才所有的操作。

在这个例子中,假如我们的操作,对 v5 进行 bad 的这个标记错了,那么,我们把这个操作之下的 Log 全部删除掉,然后执行 git bisect replay log.txt

这样就将回退到判断 v5 提交好坏的地方,重新进行标记。

在修改 Log.txt 文件的时候,最好只执行删除操作,不要对其中的顺序有所修改,毕竟我们只是想要一个回滚的动作,并不是要改动我们之前的某些操作。

今天在承香墨影公众号的后台,回复『成长』。我会送你一些我整理的学习资料,包含:Android反编译、算法、设计模式、虚拟机、Linux、Kotlin、Python、爬虫、Web项目源码。

推荐阅读:

Git 二分调试法,火速定位疑难Bug!的更多相关文章

  1. git bisect:让你闭眼都能定位疑难 bug的利器

    摘要:git bisect命令使用二分搜索算法来查找提交历史中的哪一次提交引入了错误.它几乎能让你闭着眼睛快速定位任何源码导致的问题,非常实用. 本文分享自华为云社区<利用好 git bisec ...

  2. 我的代码真的没有bug,稍等,先试试小黄鸭调试法

    今天测试同学为了赶进度,加班去测试我的功能. 因为我的代码都写完了,也没有陪测的必要,所以就没去了~ 下午第一个问题提过来,根据经验,这个应该是测试的逻辑问题,最后他自己也发现了. 过了一会,提了第二 ...

  3. 猫哥网络编程系列:HTTP PEM 万能调试法

    注:本文内容较长且细节较多,建议先收藏再阅读,原文将在 Github 上维护与更新. 在 HTTP 接口开发与调试过程中,我们经常遇到以下类似的问题: 为什么本地环境接口可以调用成功,但放到手机上就跑 ...

  4. 一个疑难bug的解决过程

    一个crontab脚本,下载一个文件并把内容入mysql数据库.具体流程如下: 1, wget一个文件. 2,处理文件生成一个中间文件. 3,将中间文件load入库. 05 10 * * * /hom ...

  5. 使用Git分支开发新特性或修复Bug与使用Git分支开发新特性或修复Bug

    使用Git分支开发新特性或修复Bug 通过分支,可以在不影响原有代码的前提下改变代码,主要用于开发新功能新特性.下 一代产品 为已经发布的正式版修复bug 团队开发时为每个人建立一个分支,从而避免相互 ...

  6. 五、git学习之——分支管理策略、Bug分支、feature分支、多人协作

    一.分支管理策略 通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息. 如果要强制禁用Fast forward模式,Git就会在merge时生 ...

  7. iOS7上的地图定位接口BUG

    遇到个BUG,卡了好久,就是在iOS9上定位接口是正常的,但是在iOS7上就一直拿不到回调,但是看系统日志其实已经定位到了.总是在报一句not response,也没有具体函数名 昨天灵机一动,从de ...

  8. Git速成学习第六课:Bug分支

    Git速成学习笔记整理于廖雪峰老师的官网网站:https://www.liaoxuefeng.com/ 当你接到一个修复代码为101的任务的时候,很自然的你想创建一个分支issue-101来修复它,但 ...

  9. git分支间切换注意点和bug分支的处理

    目录 备注: 知识点 记一次分支合并问题状况 从分支点开始,不同分支修改工作区的内容(不添加到暂存区和提交),切换分支,工作区的内容是一样的. 必须在提交或者暂存当前暂存区的状态后,再切换或合并分支 ...

随机推荐

  1. hdu 1011 Starship Troopers(树形DP入门)

    Starship Troopers Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  2. 三目运算的使用&bytes类型转str类型

    一.三目运算的使用 就像c语言中有三目运算符一样,python中也有三目运算符,废话不多说直接上代码 a=3 c=4 b=a if a>c else c print(b) 意思就和 if a&g ...

  3. Python pip 下载速度慢? Windows 设置 国内源,用 阿里云 国内镜像 加速

    pip 提供了对 Python 包的查找.下载.安装.卸载的功能,是非常方便的 Python 包管理工具.但是,令人苦恼的是 pip 在国内的下载速度非常慢,速度常常只有每秒几十 K,甚至才几 K,小 ...

  4. defer与async

    defer:该属性指定的脚本不会修改DOM,因此代码可以安全的延迟执行. 含defer属性的script标签可以放在任何位置,在页面解析到该script标签时,开始下载脚本,但不会执行脚本,直至DOM ...

  5. C# 取Visio模型信息的简易方法

    最近的一个项目,要求导出Visio图纸,因为是建筑类的,所以,需要设置墙壁,门,房间等信息的参数. 拿墙壁为例,选中墙壁模型,右键属性,会弹出以下对话框. 需要设置墙长.墙壁厚度等一些列信息. 现在C ...

  6. Linux上jdk的安装

    安装jdk    a.检测是否安装了jdk  运行java -version    b.若有需要将其卸载    c.查看安装那些jdk        rpm -qa | grep java    d. ...

  7. javaMybatis映射属性,高级映射

    映射文件的sql属性: id:标识符(一般都是dao层方法名) resultType:sql返回类型 resultMap:放回的映射类型 parameterType:参数类型 useGenerated ...

  8. Vue.js用法详解(一)更新中~

      前  言 前段时间为了一个数据查询的项目自学了Vue,感觉这款框架还是很不错的,今天就整理整理这个框架如何使用,希望对正在学这个框架的小伙伴有所帮助~ 首先,我们先来了解一下Vue: Vue.js ...

  9. java 通过eclipse编辑器用mysql尝试 连接数据库

    注:本人学的是Oracle,用mysql连接数据库是一次尝试. 一.下载JDBC mysql驱动,导入jar包     我自己下载的是connector-java-6.0.6.jar,如下图所示,JD ...

  10. MySQL原理相关

    1.索引 http://blog.codinglabs.org/articles/theory-of-mysql-index.html