ฉันได้อ่านบทความที่บอกว่ายอดgit bisectเยี่ยมมาก อย่างไรก็ตามฉันไม่ใช่เจ้าของภาษาและฉันก็ไม่เข้าใจว่าทำไมมันถึงยอดเยี่ยม
ใครก็ได้ช่วยสาธิตด้วยรหัสตัวอย่างได้บ้าง:
- วิธีใช้งาน
- มันเป็น
svn blameอย่างไร
ฉันได้อ่านบทความที่บอกว่ายอดgit bisectเยี่ยมมาก อย่างไรก็ตามฉันไม่ใช่เจ้าของภาษาและฉันก็ไม่เข้าใจว่าทำไมมันถึงยอดเยี่ยม
ใครก็ได้ช่วยสาธิตด้วยรหัสตัวอย่างได้บ้าง:
svn blameอย่างไรคำตอบ:
แนวคิดเบื้องหลังgit bisectคือทำการค้นหาแบบไบนารีในประวัติเพื่อค้นหาการถดถอยแบบเฉพาะ ลองนึกภาพว่าคุณมีประวัติการพัฒนาต่อไปนี้:
... --- 0 --- 1 --- 2 --- 3 --- 4* --- 5 --- current
คุณจะรู้ว่าโปรแกรมที่คุณทำงานไม่ถูกต้องในการแก้ไขและมันได้ทำงานที่แก้ไขcurrent 0ดังนั้นการถดถอยน่าจะนำมาใช้ในหนึ่งกระทำ1, 2, 3, 4, ,5current
คุณสามารถลองตรวจสอบการคอมมิชชันแต่ละครั้งสร้างมันตรวจสอบว่ามีการถดถอยหรือไม่ หากมีข้อผูกพันจำนวนมากการดำเนินการนี้อาจใช้เวลานาน นี่คือการค้นหาเชิงเส้น เราทำได้ดีกว่าด้วยการค้นหาแบบไบนารี นี่คือสิ่งที่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-command1
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)