Git bisect का उपयोग कैसे करें?


438

मैंने कहा है कि कुछ लेख पढ़ा है git bisect यह बहुत बढ़िया है। हालाँकि, मैं एक देशी वक्ता नहीं हूँ और मैं समझ नहीं पा रहा हूँ कि यह बहुत बढ़िया है।

क्या कोई कृपया कुछ कोड नमूने के साथ प्रदर्शित कर सकता है:

  1. इसका इस्तेमाल कैसे करें?
  2. क्या यह ऐसे ही है svn blame?

@ 01: जैसा कि गिट बुक कहती है: परियोजना के इतिहास के माध्यम से एक क्रूर बल खोज करें
Eckes

7
ऐसा नहीं है /// brute :-), यह द्विआधारी खोज का उपयोग करता है।
कोजोकर

"git blame" "svn blame" के समान है। "गिट बिसक्ट" एक पूरी तरह से अलग चीज है
विलियम पर्सल

क्या इसके लायक है, वहाँ प्रो git में भी bisect का एक अच्छा वर्णन है। सिल्वेन का जवाब इस पर एक और अच्छा शॉट है। अगर आप उन सभी को देखने के बाद भी इसे प्राप्त नहीं करते हैं, तो मेरा सुझाव है कि आप अधिक विशिष्ट प्रश्न पूछें। सामान्य प्रश्न सामान्य उत्तरों को भूल जाते हैं।
कास्कैबेल

4
अपडेटेड बुक लिंक: git-scm.com/book/en/Git-Tools-Debugging-with-Git#Binary-Search
gdelfino 15

जवाबों:


655

इसके पीछे 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 badgit 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)। यह एक छोटी जीत है, लेकिन यह इसलिए है क्योंकि हमारा इतिहास इतना छोटा है। यदि खोज सीमा एन कॉमिट्स की है, तो हमें git bisectएक रैखिक खोज के साथ लगभग 2 एन लॉग 2 के बजाय 1 + लॉग 2 एन टेस्ट करने की उम्मीद करनी चाहिए ।

एक बार जब आप कमिटेशन पेश कर देते हैं, तो आप इस समस्या का पता लगाने के लिए इसका अध्ययन कर सकते हैं। एक बार यह पूरा हो जाने के बाद, आप कमांड git bisect resetका उपयोग करने से पहले सब कुछ वापस मूल स्थिति पर रखने के लिए उपयोग करते हैं git bisect


5
मैं यहां गर्भपात करने जा रहा हूं, यह बाइसेक्ट की एक अच्छी व्याख्या है लेकिन वास्तव में इसका उपयोग करने में मेरी मदद नहीं करता है। खासकर जब से मैं एक अच्छा कमिट ढूंढने में कामयाब रहा हूं और अब मैं उस ब्रांच में हूं। इस स्थिति से यह स्पष्टीकरण बिल्कुल भी मदद नहीं करता है। मैं इसकी जाँच के बिना खराब शाखा को कैसे निर्दिष्ट कर सकता हूं, उदाहरण के लिए
पांडावुड

4
आप git bisect bad <rev> [<rev>...]विशिष्ट संशोधनों को खराब (या साथ अच्छा git bisect good <rev> [<rev>...]) के रूप में चिह्नित करने के लिए उपयोग कर सकते हैं । revशाखा नाम, एक टैग, एक प्रतिबद्ध हैश (या प्रतिबद्ध हैश का अनोखा उपसर्ग) की तरह कोई भी संशोधन पहचानकर्ता हो सकता है ...
सिल्वेन डेफ्रेसने

39
... और एक बार जब आप कर लेते हैं, तो आप git bisect resetसब कुछ हाल की प्रतिबद्ध पर वापस करने के लिए टाइप करते हैं
peetonn

17
स्टैक पर सबसे भयानक उत्तरों में से एक। बहुत अच्छी तरह से व्यक्त। मैं वर्षों से इस प्रक्रिया को मैन्युअल रूप से कर रहा हूं, बस एक अच्छा और बुरा कमिटमेंट के बीच एक मनमाना आधा बिंदु उठा रहा हूं, फिर उस एक और अच्छे / बुरे के बीच फिर यह निर्भर करता है कि क्या यह अच्छा / बुरा था। यह हमेशा से गधे में एक बहुत बड़ा दर्द रहा है और मैंने आज तक इस git उपकांड के बारे में कभी नहीं सुना था ... hahaha
Chev

3
@ नीमोडेन, हाँ, यह कर सकता है, मूल रूप से यह किसी भी प्रकार की परियोजना के लिए उपयोगी हो सकता है। आपको "वेब साइट पर तैनात" और "समस्या को पुन: उत्पन्न करने" के साथ "टेस्ट" स्टेप को बदलने की आवश्यकता है
एलेक्सा। बी

159

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 लॉग पर अच्छे और बुरे रेफरी दिखाएँ:

git log --decorate --pretty=fuller --simplify-by-decoration master

यह केवल एक संबंधित रेफरी के साथ कमिट करता है, जो शोर को कम करता है, लेकिन इसमें प्रकार के ऑटोजेनरेटेड रेफरी शामिल हैं:

refs/bisect/good*
refs/bisect/bad*

जो हमें बताता है कि हमने कौन सा अच्छा या बुरा के रूप में चिह्नित किया है।

यदि आप कमांड के साथ खेलना चाहते हैं तो इस टेस्ट रेपो पर विचार करें

असफलता तेज है, सफलता धीमी है

कभी कभी:

  • विफलता तेजी से होती है, जैसे पहले परीक्षणों में से एक टूट जाता है
  • सफलता में थोड़ा समय लगता है, जैसे कि टूटी हुई परीक्षा पास करना, और अन्य सभी परीक्षण जिनका हम पालन नहीं करते हैं

उन मामलों के लिए, उदाहरण के लिए विफलता को हमेशा 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
    

    विशेष रूप से, एक सी की assert(0)ओर जाता है 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"

2.16.1 पर परीक्षण किया गया।


7
अपने नए परीक्षण को गायब करने से कैसे पता चलेगा कि जब पिछले / बुरे संशोधन में वापस लौटकर / bisecting करने से आपके पास अपना नया लिखित परीक्षा नहीं है?
thebjorn

8
@ आपके पास एक बिंदु है: जहां तक ​​मुझे पता है, या तो परीक्षण को PATH में एक बाहरी निष्पादन योग्य होना चाहिए, या रेपो में एक अनट्रैक फ़ाइल में होना चाहिए। कई मामलों में यह संभव है: एक अलग फ़ाइल पर परीक्षण डालें, एक अच्छी तरह से तैयार किए गए test_script+ मॉड्यूलर परीक्षण सूट के साथ आवश्यक परीक्षण बॉयलरप्लेट शामिल करें , और इसे अलग फाइल से बाइसेक्टिंग करते हुए चलाएं। जब आप ठीक करते हैं, तो परीक्षण को मुख्य परीक्षण सूट में मर्ज करें।
सिरो सेंटिल्ली 郝海东 冠状 iro i

1
@CiroSantilli 六四 事件 ill ill I I क्षमा करें, मैंने आपका संपादन वापस नीचे कर दिया है, क्योंकि मैं newbies के लिए इसकी अधिक व्याख्यात्मकता महसूस कर रहा हूं और यह सिर्फ आपके उत्तर में एक और बिंदु जोड़ रहा है (आपके जैसा सटीक उत्तर नहीं - इसलिए इसका उल्लेख करते हुए, इसका) एक बिंदु जोड़ने के लिए)
Nicks

1
'गिट बाइसक्ट रन' के साथ गलत तरीके से जाने के बहुत सारे तरीके हैं - उदाहरण के लिए यह देखना कि कैसे एक अच्छा कमिट एक खराब मर्ज से उलट गया था। यह अंदर, बाहर, वापस अंदर और बाहर फिर से आता है और केवल अंतिम "आउट" खराब है। हालांकि, आप हमेशा एक मैनुअल 'गिट बायसेक्ट' कर सकते हैं। क्योंकि यह एक द्विशताब्दी है, यह केवल कुछ कदम उठाता है - जैसे 1024 10 चरणों में होता है।
कॉम्बिनेटरवादी

1
@combinatorist आप सही हैं कि यह विफल हो सकता है। bisect runजब परीक्षण समाप्त होने में बहुत समय लगता है, तो मुझे विशेष रूप से उपयोगी लगता है, और मुझे पूरा यकीन है कि परीक्षा प्रणाली नहीं टूटेगी। इस तरह, मैं इसे केवल पृष्ठभूमि पर, या रात भर चलता छोड़ सकता हूं, अगर यह बहुत सारे संसाधन लेता है, बिना किसी मस्तिष्क संदर्भ स्विच समय को खोए।
सिरो सेंटिल्ली 郝海东 冠状 iro i 法轮功 ''

124

टी एल; डॉ

शुरू:

$ 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

3
सुनिश्चित करें कि आप अपने गिट रेपो के मूल में हैं, या आपको एक अजीब बात मिलेगी "आपको इस कमांड को काम करने वाले पेड़ के टावेल से चलाने की आवश्यकता है।" त्रुटि।
पीआर व्हाइटहेड

इसलिए मैंने अपने HEAD पर बुरा किया और पहली गलती पर अच्छा किया, जब त्रुटि मौजूद नहीं थी। तो आगे क्या करना है? जब बग उपस्थित नहीं होता है तो git bisect को अगले कमिट में ले जाने के लिए अच्छा है?
गोबलींस

@Gobliins जब बग मौजूद नहीं है, तो सही, git bisect goodअगले कमिट में जाने के लिए।
ज्योफ्री हेल

40

बस एक और बिंदु जोड़ने के लिए:

हम एक फ़ाइल नाम या पथ निर्दिष्ट कर सकते हैं जब git bisect startहम जानते हैं कि बग विशेष फ़ाइलों से आया है। उदाहरण के लिए, मान लीजिए कि हम जानते हैं कि प्रतिगमन के कारण जो बदलाव कॉम / वर्किंग डायरेक्टरी में थे, उसके बाद हम इसे चला सकते हैं, git bisect start com/workingDirइसका मतलब है कि केवल उन कमिटों को बदला गया है, जो इस डायरेक्टरी की सामग्री को चेक करते हैं, और इससे चीजें और भी तेज़ हो जाती हैं।

इसके अलावा, अगर यह बताना मुश्किल है कि क्या कोई विशेष अपराध अच्छा या बुरा है, तो आप चला सकते हैं git bisect skip, जो इसे अनदेखा कर देगा। यह देखते हुए कि पर्याप्त अन्य कमिट्स हैं, git bisect खोज को संकीर्ण करने के लिए दूसरे का उपयोग करेगा।


15

$ git bisect ..बेसब्री से डिबगिंग के लिए एक Git टूल । आपकी पिछली (ज्ञात) कार्यसमिति के बाद से पिछले कमिट के माध्यम से जाने से 'गेट बिसेक्ट' डिबग करता है । यह उन सभी कमिट्स के माध्यम से जाने के लिए बाइनरी सर्च का उपयोग करता है, जो प्रतिगमन / बग पेश करता है।

$ 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

2

नोट: शर्तें 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 प्रतिबद्ध करें , Matthieu Moy ( ) द्वारा प्रतिबद्ध fe67687 (29 जून 2015 )एंटोनी डेलैइट ( ) द्वारा प्रतिबद्ध 21e5cfd (29 जून 2015) देखें । (द्वारा विलय Junio सी Hamano - - में प्रतिबद्ध 22dd6eb , 05 अक्टूबर 2015)moy
CanardChouChinois
gitster

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.