经验 - Git rerere 和 bisect

先推荐一些 GIT 的资源(部分是英文的,不过质量很不错):

  1. Github 的 Git Cheat Sheet 和 Atlassian 的 Git Cheat Sheet
  2. 想学习 branch 的话,这个网站做的特别好:https://learngitbranching.js.org/ ,每一步有详细的介绍和动态的图解,其中图解能够帮你深入理解 git。
  3. Git 的奇技淫巧(这名字翻译的):https://github.com/521xueweihan/git-tips ,原英文版:https://github.com/git-tips/tips
  4. Mac 下有一个专门的 app 学习 git 和 github:git-it-electron(基础知识,可选中文)。
  5. 还有很出名的 ohshitgit 或者 dangitgit

其实网上的文章无数,就不列举了,今天主要介绍下平时用的不多但是特别有用的2个技巧:rerere 和 bisect,bisect 我自己用的还是蛮多的,rerere 用的场景比较少,这个也有在 Laracon AU 上被讲到,我就又研究了下。

rerere

它指的是 Reuse Recorded Resolution,简单来说:它会记录 你解决一个 conflict 时的方法,当你下次再遇到同样的 conflict 时,rerere 可以自动帮你解决

首先你需要全局配置它:

git config --global rerere.enabled true
git config --global rerere.autoupdate true(可选,非必须,下面会讲)

下面举个例子来阐述,比如我在 master 和 develop 分支同时修改了 readme.md 文件,当我把 develop 分支 merge 到 master 的时候,会出现以下提示:

Auto-merging readme.md
CONFLICT (content): Merge conflict in readme.md
Recorded preimage for 'readme.md'
Automatic merge failed; fix conflicts and then commit the result.

注意 Recorded preimage for 'readme.md',它会在 .git/rr-cache 下面生成一个指纹文件夹,里面包含了一个 preimage:它记录了有冲突时的 readme.md 的整个文件内容。

当你解决冲突之后,commit 文件,会显示:

Recorded resolution for 'readme.md'.
[develop d2ec39f] fix conflict

注意 Recorded resolution for 'readme.md',你会发现之前的指纹文件夹下,多了一个 postimage:它记录了解决冲突后的 readme.md 的整个文件内容。

所以你解决这个冲突的 solution 已经被记录,以后如果你 merge 或者 rebase 再遇到同样的冲突时,git 会出现以下提醒:

Auto-merging readme.md
CONFLICT (content): Merge conflict in readme.md
Resolved 'readme.md' using previous resolution.

注意 Resolved 'readme.md' using previous resolution,说明 rerere 已经自动帮你 merge 了。如果第一步全局配置的时候 autoupdate 设置成 true 的话,会是 Staged 'readme.md' using previous resolution,区别就是它多运行了 git add 这一步。

不过 不推荐设置 autoupdate,原因是你可以再 review 下代码,确认无误后再 add 和 commit。

一个很简单的配置 真的是非常有用!

bisect

这个也特别有用,简单来说:当你突然发现项目有一个 bug,但是怎么也找不出是哪个 commit 导致该问题,bisect 可以帮你定位到

下面我就以 @summerlarabbs 代码库为例介绍下这个命令:假设在 commit 完 User default avatar after signup 后突然发现项目有一个 bug,但是你记得在 commit Admin can manage roles and permissions 时是没有问题的,那么在这两个 commit 之间有8个 commits,修改的文也件比较多,我们如何使用 bisect 找出有问题的 commit?
file
首先运行 bisect:

git bisect start

然后告诉 git 哪个 commit 没有 bug:

git bisect good 60111c2

再告诉 git 哪个 commit 已经有了 bug:

git bisect bad e80be90

此时 bisect 会提示你:

Bisecting: 4 revisions left to test after this (roughly 2 steps)
[184fc2d68113cef7494055ac8c890d73e27c5eb9] Sidebar active users

因为 bisect 采用的是二分查找(Binary Search),所以此时的 commit 会处于 184fc2d - Sidebar active users,从上面可以看出大概需要再查询2次,就能找出是哪个 commit 有问题。

这个时候你去测试下,看还有没有那个 bug,如果没有就运行:git bisect good,如果有就运行:git bisect bad,我们在这里运行下 good,会得到:

Bisecting: 2 revisions left to test after this (roughly 1 step)
[1b4fdd88a8f76584557136818526ddd2b573e6fe] Add foreign key references

可以得知还剩余1步了,此时 commit 在 1b4fdd8 - Add foreign key references,继续测试下看 bug 还在不在,假设还在的话,我们就运行下 git bisect bad:

Bisecting: 0 revisions left to test after this (roughly 0 steps)
[b70dc5b0c20c2efc8e8d30a629ec6d5318b416ce] Sidebar links

这时可以看到已剩余 0 revisions 和 steps,此时可以得出结论:是 b70dc5b - Sidebar links 这个 commit 引入了 bug,然后你再去查看下这个 commit 修改的所有文件,就能找出问题所在!

最后结束 bisect 或者需要中途退出,可以运行 git bisect reset,它会返回到原来所在的分支。

一个很简单的命令,真的是超赞!

本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 5年前 自动加精
jltxwesley
讨论数量: 6
leo

『二进制搜索』应该叫『二分查找』

5年前 评论
jltxwesley

@leo

好的我修改下,英文接触久了,有时候不知道怎么翻译好 😄

5年前 评论
Destiny

很实用的技巧 Get

5年前 评论
jltxwesley

@Destiny

嗯嗯 尤其 rerere 我也很长时间都不知道这个

5年前 评论
Destiny

@jltxwesley :smile: 哈哈,之前就用了一些常用的。这些就在手册上看过。没试。。

5年前 评论

有个问题请教下,master分支合并test分支的时候提示Already up to date,但其实是有差异的,这个什么情况?

$ git merge test
Already up to date.

 $ git status
On branch master
nothing to commit, working tree clean
#比较test分支的Test.php 有差异
 $ git diff test app/Http/Controllers/Test.php
diff --git a/app/Http/Controllers/Test.php b/app/Http/Controllers/Test.php
index 27c8be83..c40f563f 100644
--- a/app/Http/Controllers/Test.php
+++ b/app/Http/Controllers/Test.php
@@ -55,7 +55,6 @@ class Test extends Controller {
-        $return['data'] = $app ? $app['result'] : [];
     }
4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!