設定與配置
取得與建立專案
基本快照
分支與合併
共享與更新專案
檢查與比較
修補
除錯
電子郵件
外部系統
伺服器管理
指南
管理
底層命令
- 2.44.1 → 2.47.0 沒有變更
-
2.44.0
02/23/24
- 2.43.3 → 2.43.5 沒有變更
-
2.43.2
02/13/24
-
2.43.1
02/09/24
-
2.43.0
11/20/23
- 2.42.1 → 2.42.3 沒有變更
-
2.42.0
08/21/23
- 2.29.1 → 2.41.2 沒有變更
-
2.29.0
10/19/20
- 2.25.1 → 2.28.1 沒有變更
-
2.25.0
01/13/20
- 2.18.1 → 2.24.4 沒有變更
-
2.18.0
06/21/18
- 2.17.0 → 2.17.6 沒有變更
-
2.16.6
12/06/19
- 2.14.6 → 2.15.4 沒有變更
-
2.13.7
05/22/18
- 2.12.5 沒有變更
-
2.11.4
09/22/17
- 2.10.5 沒有變更
-
2.9.5
07/30/17
- 2.8.6 沒有變更
-
2.7.6
07/30/17
-
2.6.7
05/05/17
- 2.2.3 → 2.5.6 沒有變更
-
2.1.4
12/17/14
-
2.0.5
12/17/14
描述
此命令接受各種子命令,並根據子命令的不同而有不同的選項
git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>] [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...] git bisect (bad|new|<term-new>) [<rev>] git bisect (good|old|<term-old>) [<rev>...] git bisect terms [--term-(good|old) | --term-(bad|new)] git bisect skip [(<rev>|<range>)...] git bisect reset [<commit>] git bisect (visualize|view) git bisect replay <logfile> git bisect log git bisect run <cmd> [<arg>...] git bisect help
此命令使用二元搜尋演算法來尋找專案歷史記錄中引入錯誤的提交。您首先要告訴它一個已知包含錯誤的「壞」提交,以及一個已知在引入錯誤之前的「好」提交。然後 git bisect
會選取這兩個端點之間的提交,並詢問您所選取的提交是「好」還是「壞」。它會持續縮小範圍,直到找到引入變更的確切提交。
事實上,git bisect
可以用來尋找變更專案任何屬性的提交;例如,修正錯誤的提交,或導致基準測試效能提升的提交。為了支援這種更通用的用法,可以使用「舊」和「新」這兩個詞來代替「好」和「壞」,或者您可以選擇自己的詞。有關更多資訊,請參閱下方的「替代詞」章節。
基本 bisect 命令:start、bad、good
例如,假設您嘗試尋找使專案 v2.6.13-rc2
版本中已知可運作的功能損壞的提交。您可以依照以下方式啟動 bisect 會期
$ git bisect start $ git bisect bad # Current version is bad $ git bisect good v2.6.13-rc2 # v2.6.13-rc2 is known to be good
在您至少指定一個壞提交和一個好提交之後,git bisect
會選取該歷史記錄範圍中間的提交,將其簽出,然後輸出類似以下內容的訊息
Bisecting: 675 revisions left to test after this (roughly 10 steps)
您現在應該編譯簽出的版本並進行測試。如果該版本運作正常,請輸入
$ git bisect good
如果該版本損壞,請輸入
$ git bisect bad
然後 git bisect
會回應類似以下內容的訊息
Bisecting: 337 revisions left to test after this (roughly 9 steps)
持續重複此程序:編譯樹狀結構、測試它,然後根據它是好還是壞,執行 git bisect good
或 git bisect bad
來要求下一個需要測試的提交。
最後,將不會有任何修訂可供檢查,並且該命令會印出第一個壞提交的描述。參考 refs/bisect/bad
將會保持指向該提交。
Bisect reset
在 bisect 會期之後,若要清除二分狀態並返回原始 HEAD,請執行以下命令
$ git bisect reset
預設情況下,這會將您的樹狀結構返回到 git bisect start
之前簽出的提交。(新的 git bisect start
也會執行此操作,因為它會清除舊的二分狀態。)
使用可選的參數,您可以改為返回到不同的提交
$ git bisect reset <commit>
例如,git bisect reset bisect/bad
會簽出第一個壞修訂,而 git bisect reset HEAD
則會將您留在目前的二分提交,並完全避免切換提交。
替代詞
有時您不是在尋找引入損壞的提交,而是在尋找導致某些其他「舊」狀態和「新」狀態之間發生變更的提交。例如,您可能正在尋找引入特定修正的提交。或者您可能正在尋找原始碼檔案名稱最終都轉換為您公司命名標準的第一個提交。或是任何其他情況。
在這種情況下,使用「好」和「壞」這兩個詞來表示「變更之前的狀態」和「變更之後的狀態」可能會非常令人困惑。因此,您可以分別使用「舊」和「新」這兩個詞來代替「好」和「壞」。(但請注意,您無法在單個會期中混合使用「好」和「壞」以及「舊」和「新」。)
在這種更通用的用法中,您會為 git bisect
提供一個具有某些屬性的「新」提交,以及一個沒有該屬性的「舊」提交。每次 git bisect
簽出提交時,您都要測試該提交是否具有該屬性。如果有,則將提交標記為「新」;否則,將其標記為「舊」。完成二分之後,git bisect
會報告哪個提交引入了該屬性。
若要使用「舊」和「新」來代替「好」和「壞」,您必須執行 git bisect start
時不帶提交作為參數,然後執行以下命令來新增提交
git bisect old [<rev>]
以表示提交在尋求的變更之前,或
git bisect new [<rev>...]
以表示提交在變更之後。
若要取得目前所用詞的提醒,請使用
git bisect terms
您可以使用 git bisect terms --term-old
或 git bisect terms --term-good
僅取得舊詞;可以使用 git bisect terms --term-new
和 git bisect terms --term-bad
來了解如何稱呼比尋求的變更更新的提交。
如果您想使用自己的詞,而不是「壞」/「好」或「新」/「舊」,您可以選擇任何您喜歡的名稱(除了現有的 bisect 子命令,例如 reset
、start
等等),方法是使用
git bisect start --term-old <term-old> --term-new <term-new>
啟動二分。例如,如果您正在尋找引入效能倒退的提交,您可以使用
git bisect start --term-old fast --term-new slow
或者如果您正在尋找修正錯誤的提交,您可以使用
git bisect start --term-new fixed --term-old broken
然後,使用 git bisect <term-old>
和 git bisect <term-new>
來代替 git bisect good
和 git bisect bad
以標記提交。
Bisect visualize/view
若要在二分過程中於 gitk 中查看目前剩餘的可疑項目,請執行以下命令(子命令 view
可以作為 visualize
的替代方案使用)
$ git bisect visualize
Git 會透過各種環境變數偵測圖形環境:DISPLAY
,它是在 Unix 系統上的 X Window System 環境中設定的。SESSIONNAME
,它是在互動式桌面會期中於 Cygwin 下設定的。MSYSTEM
,它是在 Msys2 和 Git for Windows 下設定的。SECURITYSESSIONID
,它可能會在互動式桌面會期中於 macOS 上設定。
如果未設定這些環境變數中的任何一個,則會改用 git log。您也可以提供命令列選項,例如 -p
和 --stat
。
$ git bisect visualize --stat
Bisect log 和 bisect replay
在將修訂標記為好或壞之後,執行以下命令以顯示目前已完成的工作
$ git bisect log
如果您發現您在指定修訂的狀態時犯了錯誤,您可以將此命令的輸出儲存到檔案中,編輯它以移除不正確的項目,然後執行以下命令以返回更正的狀態
$ git bisect reset $ git bisect replay that-file
避免測試提交
如果在 bisect 會期中間,您知道建議的修訂不適合測試(例如,它無法建置,而且您知道該失敗與您正在追蹤的錯誤沒有任何關係),您可以手動選取附近的提交,然後改為測試該提交。
例如
$ git bisect good/bad # previous round was good or bad. Bisecting: 337 revisions left to test after this (roughly 9 steps) $ git bisect visualize # oops, that is uninteresting. $ git reset --hard HEAD~3 # try 3 revisions before what # was suggested
然後編譯並測試所選取的修訂,然後以一般方式將修訂標記為好或壞。
Bisect skip
您不需要自行選擇附近的提交,您可以執行以下命令,要求 Git 為您執行此操作
$ git bisect skip # Current version cannot be tested
但是,如果您跳過與您要尋找的提交相鄰的提交,Git 將無法準確地判斷這些提交中的哪一個是第一個錯誤的提交。
您也可以使用範圍表示法跳過一系列提交,而不僅僅是單個提交。例如
$ git bisect skip v2.5..v2.6
這會告知二分程序,不應該測試 v2.5
之後(直到並包括 v2.6
)的任何提交。
請注意,如果您也想跳過該範圍的第一個提交,您會執行以下命令
$ git bisect skip v2.5 v2.5..v2.6
這會告知二分程序,應該跳過 v2.5
和 v2.6
之間(包括兩者)的提交。
透過為 bisect start 提供更多參數來減少二分
如果您知道樹狀結構的哪個部分涉及您正在追蹤的問題,您可以透過在執行 bisect start
命令時指定 pathspec 參數,進一步減少試驗次數
$ git bisect start -- arch/i386 include/asm-i386
如果您預先知道多個好提交,您可以在執行 bisect start
命令時,透過在壞提交之後立即指定所有好提交來縮小二分空間
$ git bisect start v2.6.20-rc6 v2.6.20-rc4 v2.6.20-rc1 -- # v2.6.20-rc6 is bad # v2.6.20-rc4 and v2.6.20-rc1 are good
Bisect 執行
如果您有一個腳本可以判斷目前的原始碼是好還是壞,您可以透過發出以下指令來進行二分搜尋:
$ git bisect run my_script arguments
請注意,如果目前的原始碼是好的/舊的,則腳本 (在上面的範例中是 my_script
) 應該以代碼 0 結束;如果目前的原始碼是壞的/新的,則應該以介於 1 和 127(含)之間的代碼結束,但 125 除外。
任何其他結束代碼都會中止二分搜尋程序。應該注意的是,透過 exit(-1)
終止的程式會留下 $? = 255,(請參閱 exit(3) 手冊頁),因為該值會被 & 0377
截斷。
當目前的原始碼無法測試時,應使用特殊的結束代碼 125。如果腳本以此代碼結束,則會跳過目前的修訂版本 (請參閱上面的 git bisect skip
)。選擇 125 作為此目的可用的最高合理值,因為 126 和 127 由 POSIX shell 用於發出特定錯誤狀態訊號(127 用於找不到命令,126 用於找到命令但不可執行——這些細節並不重要,因為就 bisect run
而言,它們是腳本中的正常錯誤)。
您可能會經常發現在二分搜尋過程中,您想對正在測試的修訂版本進行臨時修改(例如,在標頭檔中將 s/#define DEBUG 0/#define DEBUG 1/,或者「不包含此提交的修訂版本需要應用此修補程式才能解決此二分搜尋不感興趣的另一個問題」)。
為了應對這種情況,在內部 git bisect 找到下一個要測試的修訂版本後,腳本可以在編譯之前應用修補程式,執行真正的測試,然後決定修訂版本(可能包含所需的修補程式)是否通過測試,然後將樹還原到原始狀態。最後,腳本應該以真實測試的狀態結束,讓 git bisect run
命令迴圈決定二分搜尋程序的最終結果。
範例
-
自動二分搜尋 v1.2 和 HEAD 之間損壞的建置
$ git bisect start HEAD v1.2 -- # HEAD is bad, v1.2 is good $ git bisect run make # "make" builds the app $ git bisect reset # quit the bisect session
-
自動二分搜尋 origin 和 HEAD 之間測試失敗的問題
$ git bisect start HEAD origin -- # HEAD is bad, origin is good $ git bisect run make test # "make test" builds and tests $ git bisect reset # quit the bisect session
-
自動二分搜尋損壞的測試案例
$ cat ~/test.sh #!/bin/sh make || exit 125 # this skips broken builds ~/check_test_case.sh # does the test case pass? $ git bisect start HEAD HEAD~10 -- # culprit is among the last 10 $ git bisect run ~/test.sh $ git bisect reset # quit the bisect session
在這裡,我們使用一個
test.sh
自訂腳本。在這個腳本中,如果make
失敗,我們會跳過目前的提交。如果測試案例通過,check_test_case.sh
應該exit 0
,否則應該exit 1
。如果
test.sh
和check_test_case.sh
都位於儲存庫外部,則更安全,以防止二分搜尋、make 和測試程序與腳本之間的互動。 -
自動二分搜尋臨時修改(熱修補程式)
$ cat ~/test.sh #!/bin/sh # tweak the working tree by merging the hot-fix branch # and then attempt a build if git merge --no-commit --no-ff hot-fix && make then # run project specific test and report its status ~/check_test_case.sh status=$? else # tell the caller this is untestable status=125 fi # undo the tweak to allow clean flipping to the next commit git reset --hard # return control exit $status
這會在每次測試執行之前應用來自熱修補程式分支的修改,例如,如果您的建置或測試環境發生變更,導致較舊的修訂版本可能需要較新的版本已有的修復。(請確保熱修補程式分支是基於包含在您正在二分搜尋的所有修訂版本中的提交,以便合併不會引入太多內容,或者使用
git cherry-pick
而不是git merge
。) -
自動二分搜尋損壞的測試案例
$ git bisect start HEAD HEAD~10 -- # culprit is among the last 10 $ git bisect run sh -c "make || exit 125; ~/check_test_case.sh" $ git bisect reset # quit the bisect session
這表示如果您在一行上編寫測試,則可以不用執行腳本。
-
在損壞的儲存庫中尋找物件圖的良好區域
$ git bisect start HEAD <known-good-commit> [ <boundary-commit> ... ] --no-checkout $ git bisect run sh -c ' GOOD=$(git for-each-ref "--format=%(objectname)" refs/bisect/good-*) && git rev-list --objects BISECT_HEAD --not $GOOD >tmp.$$ && git pack-objects --stdout >/dev/null <tmp.$$ rc=$? rm -f tmp.$$ test $rc = 0' $ git bisect reset # quit the bisect session
在這種情況下,當 git bisect run 完成時,bisect/bad 將參考至少有一個父系的提交,該父系的連通圖在 git pack objects 所需的意義上是完全可遍歷的。
-
尋找程式碼中的修復而不是迴歸
$ git bisect start $ git bisect new HEAD # current commit is marked as new $ git bisect old HEAD~10 # the tenth commit from now is marked as old
或
$ git bisect start --term-old broken --term-new fixed $ git bisect fixed $ git bisect broken HEAD~10
GIT
git[1] 套件的一部分