讓 Git Bisect 幫助你
讓 Git Bisect 幫助你
英文原文:Letting Git Bisect Help You
Git 提供來很多的工具來幫助我們改進工作流程。 bisect 命令就是其中之一, 雖然由於使用得不多而不廣為人知,但是當你想知道一個本來好的分支從什麽時候開始變壞時,它就能派上用場了。到底是哪一次提交把事情搞砸了呢,讓 bisect 來告訴你吧。 |
如果你有去過圖書館,那你可能註意到了每個專區內的書籍都是按作者姓名來排序的。比方說你要找的一本書的作者的姓為 Martin,而你剛剛看到某個書架上的最後一本書的作者的姓是 F 開頭的,那麽你就能確定你要找的書一定放在後面的某個書架上。依此方法繼續下次,你就能快速的縮小搜索範圍直到找到你要的書為止。 |
二分查找算法所需的比較次數通常都比你傻傻的去拿序列中的每個元素與 x 比較所需的比較次數少得多。事實證明在有序序列中查找元素,二分查找更快更有用。 BisectBisect 就是利用二分查找發來查找在你的某一分支中到底是哪一次提交引入了特定的變更。 |
有了這套檢測方法,你就可以開始用 bisect 查找你的提交歷史來以最快的速度發現引入 bug 的時間點了。等等,你還得準備好兩個提交點:一個是你確定 bug 還沒有被引入的提交點,另一個則是確定 bug 已經引入了的提交點(這樣就縮小了初始的查找範圍)。在 bisect 命令上,你可以用哈希值(hash)或者標簽(tag)來引用這兩個提交點。bisect 查找時,查找範圍裏的提交點要麽被標記為好的(通過測試,沒有 bug 的),要麽被標記為壞的(通不過測試,有 bug 的)。 上圖演示了 bisect 的執行步驟(綠點是好的提交點,紅點的就是壞的):bisect 被要求在提交點 1 到 8 這個範圍內查找首次引入 bug 的提交點(看圖一目了然是提交點 6),這裏提交點 1 和 8 就是上段中提及的,我們需要首先準備好給 bisect 命令的兩個(一好一壞)提交點。bisect 首先用調用者提供的檢測方法來測試 1 到 8 中間的提交點 4,如果它是好的(圖上的情況),那麽 bisect 就縮小範圍為它右邊的區域,重復上述步驟,反之,則選擇其左邊的區域為新的搜索範圍。如此遞歸下去,在上圖的例子中,只需要 3 步就確定了罪魁禍首是提交點 6. |
我這裏創建了一個 git 倉庫,裏面共有 1024 個提交記錄,每個提交都往一個文本文件後面添加一個遞增的數字,從 1 到 1024,一行一個數字。我們的任務是要找出是哪個提交點向文本文件附加了 1013 這個數字(我們假定它就是一個 bug)。
有了這條命令,我們就可以開始 bisect 了:
對 master 分支(的頭部提交點)運行這個測試,沒有得到想要的結果(就是沒有任何輸出),所以我們把它標記為壞的。
現在讓我們指定一個好的提交點:假設第一個提交點(7c0dcfa)是沒有 bug 的。我們可以檢出(check out)這個提交點並標記它為好的提交點(git bisect good + 該提交點的哈希值)。
也可以用下面的命令,完成上面的所有步驟: ?
git bisect start 命令可以接受兩個參數,第一個是壞的提交點,第二是好的提交點。 |
很好,git bisect 自動檢出了正中間的提交點,運行我們的檢測命令,沒有任何的輸出(沒有 bug),因此我們把該提交點標記為好的。 ?
譯者註:按照二分查找算法,bisect 根據你標記的結果,決定是檢出左半邊的中間提交點(如果你標記為 bad)還是右半邊的中間提交點(如果你標記為 good)
再次檢測,還是好的提交點。 ?
讓我們看看這些消息:除了告訴你當前新檢出的提交點以及新的搜索範圍內有多少個待測試的提交點外,它還估計出你最多還需要重復多少次測試命令就能找到你要的提交點。這次又是一個好的提交點。 ?
繼續,依然是一個好的提交點。 ?
還有 4 步,這次依然 good。 ?
這次測試命令終於有了輸出,bug 現身了!我們把這個提交點標記為壞的。 ?
終點近在咫尺,測試通過,我們把它標記為好的。 ?
壞的提交點。 ?
|
最後一步,這次是壞的。 $ git bisect bad 458eab0eb8d808e16d98ec7039a7c53855dd9ed6 is the first bad commit commit 458eab0eb8d808e16d98ec7039a7c53855dd9ed6 Author: Rodrigo Flores <[email protected]> Date: Tue Oct 21 22:31:05 2014 -0200 added 1013 :100644 100644 7bc3db7f48a43ccf1a8cc7c26146912cc88c1009 b393a2138a96c1530f41f70 1ab43cca893226976 M file.txt 我們終於得到了那個引入 1013 數字的提交點。命令 git bisect log 可以回放整個過程。 $ git bisect start # bad: [740cdf012013dc41a39b41d4b09b57a970bfe38f] added 1024 git bisect bad 740cdf012013dc41a39b41d4b09b57a970bfe38f # good: [7c0dcfa7514379151e0d83ffbf805850d2093538] added 1 git bisect good 7c0dcfa7514379151e0d83ffbf805850d2093538 # good: [8950f7db7e7cad0b2dc394ff9b75fc3d38c9d72a] added 512 git bisect good 8950f7db7e7cad0b2dc394ff9b75fc3d38c9d72a # good: [a01ba83f3500b48da97c5f5c33052623aaa4161a] added 768 git bisect good a01ba83f3500b48da97c5f5c33052623aaa4161a # good: [4a4a668bf3363d09af5fd1906bc4272aacdb4495] added 896 git bisect good 4a4a668bf3363d09af5fd1906bc4272aacdb4495 # good: [9059c5b8b898159e8d1d797bff3b1febd1fd6a1c] added 960 git bisect good 9059c5b8b898159e8d1d797bff3b1febd1fd6a1c # good: [0c844d0b33ef297b742206ebc293f4925705b083] added 992 git bisect good 0c844d0b33ef297b742206ebc293f4925705b083 # good: [0ee17eb17bd96b321a01c73eb13a8929a68b1239] added 1008 git bisect good 0ee17eb17bd96b321a01c73eb13a8929a68b1239 # bad: [dfb1e71736dcfffa2a30aecd7299f45f757c057e] added 1016 git bisect bad dfb1e71736dcfffa2a30aecd7299f45f757c057e # good: [6e6d08c374df5162fed65fed82859b69f86b936e] added 1012 git bisect good 6e6d08c374df5162fed65fed82859b69f86b936e # bad: [1d23b7045a8accd254efa859d7fc66f1f58a59f0] added 1014 git bisect bad 1d23b7045a8accd254efa859d7fc66f1f58a59f0 # bad: [458eab0eb8d808e16d98ec7039a7c53855dd9ed6] added 1013 git bisect bad 458eab0eb8d808e16d98ec7039a7c53855dd9ed6 # first bad commit: [458eab0eb8d808e16d98ec7039a7c53855dd9ed6] added 1013 這個例子裏一共有 1024 個提交點,遍歷他們我們只用了 10 步。如果提交點數量再多一倍變成 2048 個,根據二分查找算法,我們僅僅需要多加一步就能找到想要的提交點,因為二分查找算法的時間復雜度為 O(log n)。 |
自動化Git bisect 能接受一個腳本文件名作為命令參數,通過它的返回代碼判斷當前提交點的好壞。如果返回 0,就是好的提交點,返回其他值就是壞的提交點。湊巧的是,grep 命令如果找到了匹配行就會返回 0,反之返回 1。你可以使用 echo $? 命令來檢查測試命令的返回值。 grep 的返回值正好和我們的測試標準相反,所以我們需要寫一個腳本來反轉它的值(我不太習慣寫 shell 腳本,如果大家有更好的方法,感謝告知)。 ?
保存上述代碼為 test.sh,並賦予它執行權限。 接著在給 bisect 命令指定了初始的好/壞提交點之後,你只需要運行: ?
不費吹灰之力,你就得到了出問題的提交點。 |
結論你很可能不會每天都用到 bisect。也許一周用一次,甚至一個月只用到一次。但是當你想要排查出帶入問題的提交點時,bisect 確實能幫你一把。盡管並非必須,控制好每次提交的改動規模不要太大將對 bisect 排查大有幫助。如果每個提交都包含了大量的改動,那麽就算 bisect 幫你找到這個提交,你也不得不埋頭於大量的改動中苦苦搜尋 bug 的蹤跡。因此,我推薦的提交策略是嫌大不嫌多。 你呢?你經常使用 bisect 嗎? 來源: <讓 Git Bisect 幫助你 - 技術翻譯 - 開源中國社區> |
讓 Git Bisect 幫助你