ฉันได้อ่านบทความที่บอกว่ายอดgit bisect
เยี่ยมมาก อย่างไรก็ตามฉันไม่ใช่เจ้าของภาษาและฉันก็ไม่เข้าใจว่าทำไมมันถึงยอดเยี่ยม
ใครก็ได้ช่วยสาธิตด้วยรหัสตัวอย่างได้บ้าง:
- วิธีใช้งาน
- มันเป็น
svn blame
อย่างไร
ฉันได้อ่านบทความที่บอกว่ายอดgit bisect
เยี่ยมมาก อย่างไรก็ตามฉันไม่ใช่เจ้าของภาษาและฉันก็ไม่เข้าใจว่าทำไมมันถึงยอดเยี่ยม
ใครก็ได้ช่วยสาธิตด้วยรหัสตัวอย่างได้บ้าง:
svn blame
อย่างไรคำตอบ:
แนวคิดเบื้องหลังgit bisect
คือทำการค้นหาแบบไบนารีในประวัติเพื่อค้นหาการถดถอยแบบเฉพาะ ลองนึกภาพว่าคุณมีประวัติการพัฒนาต่อไปนี้:
... --- 0 --- 1 --- 2 --- 3 --- 4* --- 5 --- current
คุณจะรู้ว่าโปรแกรมที่คุณทำงานไม่ถูกต้องในการแก้ไขและมันได้ทำงานที่แก้ไขcurrent
0
ดังนั้นการถดถอยน่าจะนำมาใช้ในหนึ่งกระทำ1
, 2
, 3
, 4
, ,5
current
คุณสามารถลองตรวจสอบการคอมมิชชันแต่ละครั้งสร้างมันตรวจสอบว่ามีการถดถอยหรือไม่ หากมีข้อผูกพันจำนวนมากการดำเนินการนี้อาจใช้เวลานาน นี่คือการค้นหาเชิงเส้น เราทำได้ดีกว่าด้วยการค้นหาแบบไบนารี นี่คือสิ่งที่git bisect
คำสั่งทำ ในแต่ละขั้นตอนจะพยายามลดจำนวนการแก้ไขที่อาจแย่ลงครึ่งหนึ่ง
คุณจะใช้คำสั่งเช่นนี้:
$ git stash save
$ git bisect start
$ git bisect bad
$ git bisect good 0
Bisecting: 2 revisions left to test after this (roughly 2 steps)
[< ... sha ... >] 3
หลังจากคำสั่งนี้git
จะชำระเงินการกระทำ 3
ในกรณีของเราก็จะได้รับการกระทำ คุณต้องสร้างโปรแกรมของคุณและตรวจสอบว่ามีการถดถอยหรือไม่ คุณจะต้องบอกgit
สถานะของการแก้ไขนี้ด้วยgit bisect bad
หากมีการถดถอยหรือgit bisect good
ไม่
สมมุติว่าการถดถอยนั้นเกิด4
ขึ้น git
จากนั้นถดถอยคือไม่ได้อยู่ในการแก้ไขนี้และเราจะบอกให้
$ make
$ make test
... ... ...
$ git bisect good
Bisecting: 0 revisions left to test after this (roughly 1 step)
[< ... sha ... >] 5
จากนั้นจะทำการชำระเงินอีกครั้ง อาจเป็น4
หรือ5
(เนื่องจากมีเพียงสองคอมมิต) 5
สมมติว่ามันเลือก หลังจากสร้างเราทดสอบโปรแกรมและดูว่ามีการถดถอย จากนั้นเราบอกให้git
:
$ make
$ make test
... ... ...
$ git bisect bad
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[< ... sha ... >] 4
เราทดสอบการแก้ไขครั้งสุดท้าย, 4
. และเนื่องจากมันเป็นสิ่งหนึ่งที่แนะนำการถดถอยที่เราบอกให้git
:
$ make
$ make test
... ... ...
$ git bisect bad
< ... sha ... > is the first bad commit
< ... commit message ... >
ในสถานการณ์แบบนี้เราจะมีการทดสอบ 3 รุ่น ( 3
, 4
, 5
) แทน 4 ( 1
, 2
, 3
, 4
) นี่เป็นชัยชนะเล็กน้อย แต่เป็นเพราะประวัติของเรานั้นเล็กมาก หากช่วงการค้นหาของ N กระทำเราควรคาดว่าจะทดสอบ 1 + log2 N กระทำด้วยgit bisect
แทนที่จะเป็น N / 2 ประมาณด้วยการค้นหาเชิงเส้น
เมื่อคุณพบความมุ่งมั่นที่นำการถดถอยมาใช้คุณสามารถศึกษาเพื่อค้นหาปัญหา เมื่อเสร็จแล้วคุณสามารถใช้git bisect reset
ทุกอย่างกลับสู่สถานะเดิมก่อนที่จะใช้git bisect
คำสั่ง
git bisect bad <rev> [<rev>...]
เพื่อทำเครื่องหมายการแก้ไขเฉพาะว่าไม่ดี (หรือดีกับgit bisect good <rev> [<rev>...]
) rev
สามารถเป็นตัวระบุการแก้ไขใด ๆ เช่นชื่อสาขา, แท็ก, แฮชการกระทำ (หรือคำนำหน้าเฉพาะของแฮชการกระทำ), ...
git bisect reset
จะพิมพ์ทุกอย่างกลับคืนมาในการกระทำล่าสุด
git bisect run
แบ่งครึ่งอัตโนมัติหากคุณมี./test
สคริปต์อัตโนมัติที่มีสถานะออก 0 หากการทดสอบไม่เป็นไรคุณสามารถค้นหาข้อบกพร่องด้วยbisect run
:
git checkout KNOWN_BAD_COMMIT
git bisect start
# Confirm that our test script is correct, and fails on the bad commit.
./test
# Should output != 0.
echo $?
# Tell Git that the current commit is bad.
git bisect bad
# Same for a known good commit in the past.
git checkout KNOWN_GOOD_COMMIT
./test
# Should output 0.
echo $?
# After this, git automatically checks out to the commit
# in the middle of KNOWN_BAD_COMMIT and KNOWN_GOOD_COMMIT.
git bisect good
# Bisect automatically all the way to the first bad or last good rev.
git bisect run ./test
# End the bisect operation and checkout to master again.
git bisect reset
สิ่งนี้ถือว่าแน่นอนว่าหากสคริปต์ทดสอบ./test
ถูกติดตามคอมไพล์มันจะไม่หายไปกับการคอมมิชชันก่อนหน้านี้บางส่วนในระหว่างการแบ่งส่วน
ฉันพบว่าบ่อยครั้งที่คุณสามารถหนีไปได้โดยเพียงแค่คัดลอกสคริปต์ในต้นไม้ออกจากต้นไม้และอาจเล่นกับPATH
ตัวแปรที่คล้ายกันและเรียกใช้จากที่นั่นแทน
แน่นอนถ้าโครงสร้างพื้นฐานการทดสอบที่test
ขึ้นอยู่กับการแบ่งที่เก่ากว่านั้นไม่มีวิธีแก้ปัญหาและคุณจะต้องทำสิ่งต่างๆด้วยตนเองตัดสินใจว่าจะทดสอบแบบใดแบบหนึ่งต่อหนึ่ง
ฉันได้พบว่าการใช้ระบบอัตโนมัตินี้มักจะใช้งานได้และสามารถประหยัดเวลาได้มากสำหรับการทดสอบที่ช้าลงซึ่งค้างอยู่ในงานที่ค้างซึ่งคุณสามารถปล่อยให้มันทำงานข้ามคืนและอาจมีข้อผิดพลาดของคุณในเช้าวันรุ่งขึ้น ลอง
อยู่ที่การคอมมิทครั้งแรกที่ล้มเหลวหลังจากแบ่งออกเป็นสองส่วนแทนที่จะกลับไปที่master
:
git bisect reset HEAD
start
+ เริ่มต้นbad
และgood
ในครั้งเดียว:
git bisect start KNOWN_BAD_COMMIT KNOWN_GOOD_COMMIT~
เหมือนกับ:
git checkout KNOWN_BAD_COMMIT
git bisect start
git bisect bad
git bisect good KNOWN_GOOD_COMMIT
ดูสิ่งที่ได้รับการทดสอบแล้ว (ด้วยตนเองgood
และbad
หรือrun
):
git bisect log
ตัวอย่างผลลัพธ์:
git bisect log
git bisect start
# bad: [00b9fcdbe7e7d2579f212b51342f4d605e53253d] 9
git bisect bad 00b9fcdbe7e7d2579f212b51342f4d605e53253d
# good: [db7ec3d602db2d994fe981c0da55b7b85ca62566] 0
git bisect good db7ec3d602db2d994fe981c0da55b7b85ca62566
# good: [2461cd8ce8d3d1367ddb036c8f715c7b896397a5] 4
git bisect good 2461cd8ce8d3d1367ddb036c8f715c7b896397a5
# good: [8fbab5a3b44fd469a2da3830dac5c4c1358a87a0] 6
git bisect good 8fbab5a3b44fd469a2da3830dac5c4c1358a87a0
# bad: [dd2c05e71c246f9bcbd2fbe81deabf826c54be23] 8
git bisect bad dd2c05e71c246f9bcbd2fbe81deabf826c54be23
# bad: [c536b1b7242d5fcf92cd87e9a534bedb1c0c9c05] 7
git bisect bad c536b1b7242d5fcf92cd87e9a534bedb1c0c9c05
# first bad commit: [c536b1b7242d5fcf92cd87e9a534bedb1c0c9c0
แสดงการอ้างอิงที่ดีและไม่ดีในบันทึกการคอมไพล์เพื่อให้ได้แนวคิดที่ดีขึ้น:
git log --decorate --pretty=fuller --simplify-by-decoration master
สิ่งนี้แสดงเฉพาะการคอมมิชชันด้วยการอ้างอิงที่สอดคล้องกันซึ่งจะช่วยลดเสียงรบกวน grealy แต่รวมถึง refs ประเภทที่สร้างอัตโนมัติ:
refs/bisect/good*
refs/bisect/bad*
ซึ่งบอกเราว่าเรามุ่งมั่นทำอะไรดีหรือไม่ดี
พิจารณาrepo ทดสอบนี้หากคุณต้องการเล่นกับคำสั่ง
บางครั้ง:
สำหรับกรณีเหล่านั้นเช่นสมมติว่าความล้มเหลวมักเกิดขึ้นภายใน 5 วินาทีและหากเราขี้เกียจที่จะทำให้การทดสอบมีความเฉพาะเจาะจงมากขึ้นอย่างที่เราควรเราสามารถใช้timeout
ใน:
#!/usr/bin/env bash
timeout 5 test-command
if [ $? -eq 1 ]; then
exit 1
fi
นี้ทำงานตั้งแต่timeout
ออก124
ในขณะที่ความล้มเหลวของการออกtest-command
1
git bisect run
ค่อนข้างพิถีพิถันเกี่ยวกับสถานะทางออก:
อะไรที่สูงกว่า 127 ทำให้การแบ่งเป็นสองส่วนล้มเหลวด้วยบางสิ่งเช่น:
git bisect run failed:
exit code 134 from '../test -aa' is < 0 or >= 128
โดยเฉพาะอย่างยิ่ง C assert(0)
นำไปสู่ a SIGABRT
และออกด้วยสถานะ 134 ซึ่งน่ารำคาญมาก
125 git bisect skip
คือความมหัศจรรย์และทำให้การทำงานข้ามกับ
ความตั้งใจนี้เพื่อช่วยข้ามงานสร้างที่เสียหายเนื่องจากเหตุผลที่ไม่เกี่ยวข้อง
ดูman git-bisect
รายละเอียดที่
ดังนั้นคุณอาจต้องการใช้สิ่งที่ชอบ:
#!/usr/bin/env bash
set -eu
./build
status=0
./actual-test-command || status=$?
if [ "$status" -eq 125 ] || [ "$status" -gt 127 ]; then
status=1
fi
exit "$status"
ทดสอบบน git 2.16.1
test_script
ชุดการทดสอบที่สร้างขึ้นอย่างดี+ โมดูลาร์และเรียกใช้จากไฟล์แยกต่างหากในขณะที่ตัด เมื่อคุณแก้ไขรวมการทดสอบในชุดทดสอบหลัก
bisect run
มีประโยชน์เป็นพิเศษเมื่อการทดสอบใช้เวลานานกว่าจะเสร็จสิ้นและฉันค่อนข้างมั่นใจว่าระบบทดสอบจะไม่หยุด ด้วยวิธีนี้ฉันสามารถปล่อยให้มันรันบนพื้นหลังหรือข้ามคืนถ้าใช้ทรัพยากรมากเกินไปโดยไม่สูญเสียเวลาสลับบริบทสมอง
$ git bisect start
$ git bisect bad
$ git bisect good <goodcommit>
Bisecting: X revisions left to test after this (roughly Y steps)
ปัญหายังคงมีอยู่?
$ git bisect bad
$ git bisect good
<abcdef> is the first bad commit
git bisect reset
git bisect good
เพื่อย้ายไปยังการคอมมิชชันต่อไป
เพียงเพิ่มจุดเพิ่มเติม:
เราสามารถระบุชื่อไฟล์หรือพา ธ git bisect start
ในกรณีที่เรารู้ว่าบั๊กนั้นมาจากไฟล์บางไฟล์ ตัวอย่างเช่นสมมติว่าเรารู้ว่าการเปลี่ยนแปลงที่ทำให้เกิดการถดถอยอยู่ในไดเรกทอรี com / workingDir จากนั้นเราสามารถเรียกใช้git bisect start com/workingDir
ซึ่งหมายความว่าเฉพาะการกระทำที่เปลี่ยนแปลงเนื้อหาของไดเรกทอรีนี้จะถูกตรวจสอบและสิ่งนี้ทำให้เร็วขึ้น
นอกจากนี้หากเป็นการยากที่จะบอกว่าการกระทำที่เฉพาะเจาะจงนั้นดีหรือไม่ดีคุณสามารถวิ่งgit bisect skip
ได้ซึ่งจะเพิกเฉย เนื่องจากมีคอมมิชชันอื่นเพียงพอ gis bisect จะใช้อีกอันเพื่อ จำกัด การค้นหาแทน
$ git bisect ..
bascically เครื่องมือ Git สำหรับการแก้จุดบกพร่อง debugs 'Git Bisect' โดยดำเนินการก่อนหน้านี้ตั้งแต่การกระทำครั้งสุดท้าย (รู้จัก) การกระทำของคุณ มันใช้การค้นหาแบบไบนารี่เพื่อให้ผ่านการกระทำเหล่านั้นทั้งหมดเพื่อไปยังอันที่แนะนำการถดถอย / บั๊ก
$ git bisect start
# เริ่มต้นแบ่งออกเป็นสองส่วน
$ git bisect bad
# ระบุว่ากระทำปัจจุบัน (v1.5) มีการถดถอย / การตั้งค่าจุด 'ไม่ดี'
$ git bisect good v1.0
# พูดถึงการกระทำที่ดีครั้งสุดท้ายกระทำ (โดยไม่ต้องถดถอย)
การกล่าวถึงจุด 'ไม่ดี' และ 'ดี' นี้จะช่วยให้แบ่งออกเป็นสองส่วน (การค้นหาแบบไบนารี) เลือกองค์ประกอบกลาง (ส่ง v1.3) หากการถดถอยอยู่ที่การมอบหมาย v1.3 คุณจะตั้งเป็นจุด 'ไม่ดี' ใหม่ ( ดี -> v1.0 และไม่ดี -> v1.3 )
$ git bisect bad
หรือในทำนองเดียวกันถ้าการกระทำ v1.3 ปราศจากข้อผิดพลาดคุณจะตั้งเป็น 'จุดดี' ใหม่ (* ดี -> v1.3 และไม่ดี -> v1.6)
$ git bisect good
หมายเหตุ: เงื่อนไขgood
และbad
ไม่ใช่สิ่งเดียวที่คุณสามารถใช้สำหรับการทำเครื่องหมายการกระทำที่มีหรือไม่มีคุณสมบัติบางอย่าง
Git 2.7 (Q4 2015) เปิดgit bisect
ตัวตัวเลือกใหม่
git bisect start [--term-{old,good}=<term> --term-{new,bad}=<term>]
[--no-checkout] [<bad> [<good>...]] [--] [<paths>...]
ด้วยการเพิ่มเอกสาร:
บางครั้งคุณไม่ได้มองหาการกระทำที่ก่อให้เกิดความเสียหาย แต่เป็นการกระทำที่ก่อให้เกิดการเปลี่ยนแปลงระหว่างรัฐ "เก่า" และรัฐ "ใหม่"และรัฐ
ตัวอย่างเช่นคุณอาจกำลังมองหาการคอมมิชชันที่แนะนำการแก้ไขเฉพาะ
หรือคุณอาจมองหาการคอมมิทครั้งแรกที่ชื่อไฟล์ซอร์สโค้ดถูกแปลงเป็นมาตรฐานการตั้งชื่อ บริษัท ของคุณในที่สุด หรืออะไรก็ตามในกรณีเช่นนี้อาจทำให้เกิดความสับสนมากในการใช้คำว่า "ดี" และ "ไม่ดี" เพื่ออ้างถึง "สถานะก่อนการเปลี่ยนแปลง" และ "สถานะหลังการเปลี่ยนแปลง"
ดังนั้นคุณสามารถใช้คำว่า "
old
" และ "new
", ตามลำดับแทน "good
" และ "bad
"
(แต่โปรดทราบว่าคุณไม่สามารถผสม "good
" และ "bad
" กับ "old
" และ "new
" ในเซสชันเดียว)ในการใช้งานทั่วไปที่มากกว่านี้คุณต้องระบุ
git bisect
"new
" การกระทำมีคุณสมบัติบางอย่างและ "old
" กระทำที่ไม่มีคุณสมบัตินั้นในแต่ละครั้งที่
git bisect
ตรวจสอบการกระทำคุณจะทดสอบว่าการส่งนั้นมีคุณสมบัติ
หรือไม่: ถ้าใช่ให้ทำเครื่องหมายการส่ง "new
"; มิฉะนั้นให้ทำเครื่องหมายว่า "old
"เมื่อทำการแบ่งออกเป็นสองส่วน
git bisect
จะรายงานว่าคอมมิชชันใดที่แนะนำคุณสมบัติ
ดูกระทำ 06e6a74 , กระทำ 21b55e3 , กระทำ fe67687 (29 มิถุนายน 2015) โดยMatthieu Moy (moy
)
ดูกระทำ 21e5cfd (29 มิถุนายน 2015) โดยแอนทอน Delaite (CanardChouChinois
)
(รวมโดยJunio C Hamano - gitster
-ในการกระทำ 22dd6eb , 5 ตุลาคม 2015)