利用好 git bisect 這把利器,幫助你快速定位疑難 Bug

語言: CN / TW / HK

點選上方  前端Q ,關注公眾號

回覆 加群 ,加入前端Q技術交流群

使用git bisect二分法定位問題的基本步驟:

  1. git bisect start [最近的出錯的commitid] [較遠的正確的commitid]

  2. 測試相應的功能

  3. git bisect good 標記正確

  4. 直到出現問題則 標記錯誤 git bisect bad

  5. 提示的commitid就是導致問題的那次提交

問題描述

我們以 Vue DevUI [1] 元件庫的一個bug舉例子:chestnut:

5d14c34b 這一次commit,執行 yarn build 報錯,報錯資訊如下:

✓ building client + server bundles...
✖ rendering pages...
build error:
 ReferenceError: document is not defined
複製程式碼

我可以確定的是上一次發版本( d577ce4 [2] )是可以build成功的。

git bisect 簡介

git bisect 命令使用二分搜尋演算法來查詢提交歷史中的哪一次提交引入了錯誤。它幾乎能讓你閉著眼睛快速定位任何原始碼導致的問題,非常實用。

你只需要告訴這個命令一個包含該bug的壞 commit ID 和一個引入該bug之前的好 commit ID ,這個命令會用二分法在這兩個提交之間選擇一箇中間的 commit ID ,切換到那個 commit ID 的程式碼,然後詢問你這是好的 commit ID 還是壞的 commit ID ,你告訴它是好還是壞,然後它會不斷縮小範圍,直到找到那次引入bug的凶手 commit ID

這樣我們就只需要分析那一次提交的程式碼,就能快速定位和解決這個bug(具體定位的時間取決於該次提交的程式碼量和你的經驗),所以我們提交程式碼時一定要養成小批量提交的習慣,每次只提交一個小的獨立功能,這樣出問題了,定位起來會非常快。

接下來我就以 Vue DevUI [3] 之前出現過的一個bug為例,詳細介紹下如何使用 git bisect 這把利器。

定位過程

git bisect start 5d14c34b d577ce4
or
git bisect start HEAD d577ce4
複製程式碼

其中 5d14c34b 這次是最近出現的有bug的提交, d577ce4 這個是上一次發版本沒問題的提交。

執行完啟動 bisect 之後,馬上就切到中間的一次提交啦,以下是列印結果:

kagol:vue-devui kagol$ git bisect start 5d14c34b d577ce4
Bisecting: 11 revisions left to test after this (roughly 4 steps)
[1cfafaaa58e03850e0c9ddc4246ae40d18b03d71] fix: read-tip icon樣式洩露 (#54)
複製程式碼

可以看到已經切到以下提交:

[1cfafaaa] fix: read-tip icon樣式洩露 (#54)
複製程式碼

執行命令:

yarn build
複製程式碼

構建成功,所以標記下 good

git bisect good
複製程式碼
kagol:vue-devui kagol$ git bisect good
Bisecting: 5 revisions left to test after this (roughly 3 steps)
[c0c4cc1a25c5c6967b85100ee8ac636d90eff4b0] feat(drawer): add service model (#27)
複製程式碼

標記萬 good ,馬上又通過二分法,切到了一次新的提交:

[c0c4cc1a] feat(drawer): add service model (#27)
複製程式碼

再次執行 build 命令:

yarn build
複製程式碼

build失敗了,出現了我們最早遇到的報錯:

✓ building client + server bundles...
✖ rendering pages...
build error:
 ReferenceError: document is not defined
複製程式碼

標記下 bad ,再一次切到中間的提交:

kagol:vue-devui kagol$ git bisect bad
Bisecting: 2 revisions left to test after this (roughly 2 steps)
[86634fd8efd2b808811835e7cb7ca80bc2904795] feat: add scss preprocessor in docs && fix:(Toast)  single lifeMode bug in Toast 
複製程式碼

以此類推,不斷地驗證、標記、驗證、標記...最終會提示我們那一次提交導致了這次的bug,提交者、提交時間、提交message等資訊。

kagol:vue-devui kagol$ git bisect good
c0c4cc1a25c5c6967b85100ee8ac636d90eff4b0 is the first bad commit
commit c0c4cc1a25c5c6967b85100ee8ac636d90eff4b0
Author: nif <[email protected]>
Date:   Sun Dec 26 21:37:05 2021 +0800

    feat(drawer): add service model (#27)
    
    * feat(drawer): add service model
    
    * docs(drawer): add service model demo
    
    * fix(drawer): remove 'console.log()'

 packages/devui-vue/devui/drawer/index.ts           |  7 +++--
 .../devui-vue/devui/drawer/src/drawer-service.ts   | 33 ++++++++++++++++++++++
 packages/devui-vue/devui/drawer/src/drawer.tsx     |  3 ++
 packages/devui-vue/docs/components/drawer/index.md | 29 +++++++++++++++++++
 4 files changed, 69 insertions(+), 3 deletions(-)
 create mode 100644 packages/devui-vue/devui/drawer/src/drawer-service.ts
複製程式碼

最終定位到出問題的commit:

c0c4cc1a is the first bad commit
複製程式碼

github.com/DevCloudFE/… [4]

整個定位過程幾乎是機械的操作,不需要了解專案原始碼,不需要了解最近誰提交了什麼內容,只需要無腦地:驗證、標記、驗證、標記,最後git會告訴我們那一次提交出錯。

這麼香的工具,趕緊來試試吧!

問題分析

直到哪個commit出問題了,定位起來範圍就小了很多。

如果平時提交程式碼又能很好地遵循小顆粒提交的話,bug呼之欲出。

這裡必須表揚下我們DevUI的田主(Contributor)們,他們都養成了小顆粒提交的習慣,這次導致bug的提交 c0c4cc1a ,只提交了4個檔案,涉及70多行程式碼。

image.png

我們在其中搜索下 document 關鍵字,發現了兩處,都在 drawer-service.ts 整個檔案中:

一處是12行的:

static $body: HTMLElement | null = document.body
複製程式碼

另一處是17行的:

this.$div = document.createElement('div')
複製程式碼
image.png

最終發現罪魁禍首就是12行的程式碼!

破案!

此處@lnzhangsong我們的田主,有空麻煩修下這個bug。

image.png

關於本文

來源:DevUI團隊

https://juejin.cn/post/7046409685561245733

往期推薦

最後

  • 歡迎加我微信,拉你進技術群,長期交流學習...

  • 歡迎關注「前端Q」,認真學前端,做個專業的技術人...

點個 在看 支援我吧