14 पॉइंट द्वारा GN⁺ 2025-11-04 | 2 टिप्पणियां | WhatsApp पर शेयर करें
  • बाइनरी सर्च (binary search) की अवधारणा सिर्फ़ interview problems तक सीमित नहीं है, बल्कि वास्तविक development tool Git में भी इस्तेमाल होती है
  • बड़े monorepo environment में जब test अचानक fail होने लगते हैं, तो सिर्फ़ logs के आधार पर कारण का पता लगाना मुश्किल हो सकता है
  • एक सहकर्मी ने good commit और bad commit तय करके git bisect से automated search चलाया और bug की शुरुआत करने वाले problematic commit को सटीक रूप से ढूँढ निकाला
  • हर चरण में script चलाकर test result के आधार पर commits को अपने-आप classify किया जाता है, और पहले fail होने वाले commit की पहचान की जाती है
  • binary search के सिद्धांत का उपयोग करने वाला git bisect बड़े codebase में bug के कारण को तेज़ी से ट्रैक करने का एक शक्तिशाली tool है

एल्गोरिद्म और वास्तविक उदाहरण

  • बाइनरी सर्च (binary search) एल्गोरिद्म सिर्फ़ एक साधारण interview problem नहीं है, बल्कि वास्तविक debugging tools में भी एक मुख्य सिद्धांत के रूप में काम करता है
  • git bisect एक ऐसा tool है जो “bug को पहली बार introduce करने वाले commit (first bad commit)” को ढूँढने के लिए binary search का उपयोग करता है
    • यह Leetcode की “First Bad Version” समस्या जैसे ही सिद्धांत पर काम करता है

वास्तविक कामकाजी माहौल में समस्या की स्थिति

  • बड़े monorepo का उपयोग करने वाले environment में हर दिन सैकड़ों से हज़ारों commits हो सकते हैं
  • किसी खास test failure का कारण सिर्फ़ logs से ट्रैक करना मुश्किल होता है
  • failure का कारण remote call के लिए ज़रूरी token प्राप्त करने वाले configuration file में string change था, जिससे वह दूसरे account को refer करने लगा और test fail हो गया
  • यह बदलाव integration test से पास हो गया था, लेकिन वास्तव में समस्या पैदा कर रहा था, और इतने सारे commits में यह किस बिंदु पर हुआ, इसे ढूँढना कठिन था

git bisect से समस्या का समाधान

  • दूसरी team के एक सहकर्मी ने git bisect command का उपयोग करके problematic commit को तेज़ी से identify किया
    • good commit और bad commit तय करने के बाद यह अपने-आप बीच के commits को checkout करके tests चलाता है और कारण को धीरे-धीरे सीमित करता जाता है
    • हर test run में समय लगा, लेकिन अंत में ठीक वही commit मिल गया जिसने समस्या introduce की थी
    • उस commit को revert करते ही सभी tests फिर से सामान्य हो गए

git bisect चलने की प्रक्रिया

  • उदाहरण commit history
    • Commit 1: initial commit (सामान्य)
    • Commit 2: refactoring (सामान्य)
    • Commit 3: bug introduced (error हुआ)
    • Commit 4~10: non-functional changes (error बना रहता है)
  • command example
    git bisect start  
    git bisect bad HEAD  
    git bisect good HEAD~9  
    git bisect run ./test_script.sh  
    
  • test script (test_script.sh) सफल होने पर 0 और fail होने पर non-zero code लौटाती है
  • git bisect अपने-आप बीच के commits को checkout करता है और test script चलाता है,
    और test fail होने के बिंदु के आधार पर पहले bad commit की पहचान करता है
  • output में b982ed9373fe235fe61c74b15faf264bc7142398 commit को पहले bug commit के रूप में पुष्टि की गई

निष्कर्ष

  • git bisect binary search के सिद्धांत को code history की खोज में लागू करने वाला एक व्यावहारिक tool है
  • बड़े repository या जटिल बदलाव इतिहास में भी bug introduce होने के समय को तेज़ी से ट्रैक किया जा सकता है
  • test automation के साथ मिलाकर बड़े codebase में भी स्थिर debugging संभव हो जाती है

2 टिप्पणियां

 
kandk 2025-11-04

इन्हीं समस्याओं की वजह से हम TBD(trunk-based-develop) का इस्तेमाल करते हैं।

 
GN⁺ 2025-11-04
Hacker News की राय
  • पहले जब मैं एक बहुत बड़े codebase पर काम करता था, जहाँ test coverage भी नहीं थी और abstraction भी बुरी तरह बिखरा हुआ था, तब git bisect लगभग इकलौता काम का tool था
    code इतना जटिल था कि bug को तार्किक तरीके से trace करना नामुमकिन था, इसलिए यह पता लगाना कहीं ज़्यादा आसान था कि किस commit में समस्या आई
    लेकिन high-quality codebase में bisect की ज़रूरत ज़्यादा नहीं पड़ी। हर component को independently test किया जा सकता था, और observability भी अच्छी थी, इसलिए यह साफ़ होता था कि कहाँ देखना है

    • मुझे नहीं लगता कि git bisect कभी बेकार होता है। यह सिर्फ bug ढूँढने के लिए नहीं, बल्कि यह समझने में भी मदद करता है कि वह bug क्यों आया
      अगर किसी project में commit messages अच्छे हों, तो bisect के ज़रिए पुराने commits का context समझा जा सकता है और उसे bug-fix commit में शामिल किया जा सकता है। इस तरह का चक्र commit culture को और मज़बूत करता है
    • मैंने एक बार एक OSS program में अजीब string वाली bug ढूँढी थी। वह C code था और वजह uninitialized variable थी
      सीधे trace करना संभव नहीं था, लेकिन bisect script लिखकर करीब 30 मिनट चलाया और सही commit सटीक रूप से मिल गया
    • git bisect मूल रूप से Linux kernel regression ढूँढने के लिए लाया गया tool था
      hardware driver जैसे मामलों में जहाँ test करना संभव नहीं होता, वहाँ भी आम user खुद kernel को bisect करके problematic commit की पहचान कर सकता था
      पहले developers से email के ज़रिए मदद माँगनी पड़ती थी, लेकिन अब user खुद समस्या को सीमित कर सकता है
    • अगर मकसद सिर्फ bug ठीक करना है, तो शायद bisect की ज़रूरत न पड़े। लेकिन कभी-कभी यह जानना ज़रूरी होता है कि bug कब से मौजूद है
      उदाहरण के लिए, गलत तरीके से process हुए data की सीमा trace करने में, या यह तय करने में कि “यह bug है या feature”, यह काफ़ी उपयोगी है
    • कभी-कभी यह जानना भी ज़रूरी होता है कि bug कब ठीक हुआ था
      जैसे अगर कोई customer 6 साल पुराने version में समस्या झेल रहा हो, तो यह जाँचा जा सकता है कि 4 साल पुराने version पर upgrade करने से समस्या हल होगी या नहीं
      या जब code का बड़ा refactoring हुआ हो, तब यह भी समझा जा सकता है कि bug fix जानबूझकर किया गया था या संयोग से हुआ
  • git bisect जब सही काम करता है तो शानदार है, लेकिन यह हर bug नहीं ढूँढ सकता
    कुछ bugs ऐसे होते हैं जिनके लक्षण introduce होने के समय नहीं दिखते, और बाद के किसी दूसरे बदलाव से सामने आते हैं
    ऐसे मामलों में bisect की यह धारणा टूट जाती है कि अच्छे commit और बुरे commit के बीच bug सिर्फ एक बार आया होगा
    जिन commits को test नहीं किया जा सकता, उन्हें skip किया जा सकता है, लेकिन अगर वही problematic commit हो तो नतीजा अस्पष्ट हो जाता है

  • हाल ही में मैंने पहली बार गंभीरता से git bisect इस्तेमाल किया, और यह लगभग जादू जैसा लगा
    एक ही नाम के दो functions थे, और code formatting के दौरान सही function का import हट गया था, जिससे समस्या हुई
    मैंने कई बार code review किया, लेकिन bisect से problematic commit पहचानने तक वजह का बिल्कुल पता नहीं चला

  • मैं आम तौर पर पहले से जानता हूँ कि bug किस file या function के दायरे में है, इसलिए bisect ज़्यादा इस्तेमाल नहीं करता
    उसकी जगह मैं git log -L :func_name:path/to/file.c command से किसी खास function की change history trace करता हूँ
    इसके लिए .gitattributes setting चाहिए

    • किसी ने पूछा था कि .gitattributes setting कैसी होनी चाहिए। उसे इस बारे में और जानने में दिलचस्पी थी
    • किसी ने कहा कि वह हर दिन bisect इस्तेमाल करता है। उसका workflow पूरी तरह अलग था
    • C++ जैसी भाषाओं में जहाँ polymorphic functions होती हैं, वहाँ git log -L कमज़ोर पड़ता है। एक ही नाम वाले overloaded functions में किसी खास version को trace करना मुश्किल होता है
    • अगर .gitattributes न हो, तो git log -S से किसी खास string वाले commits खोजना भी एक तरीका है
  • test script में exit code 125 जानना उपयोगी है
    build failure जैसी स्थिति में, जहाँ test result तय नहीं किया जा सकता, 125 return करने पर bisect उस commit को छोड़ देता है
    मैंने इससे जुड़ी बात अपने blog post में लिखी है

    • जिन repositories में merge commit, CI pass होने वाले points को दिखाते हैं, वहाँ git bisect --first-parent उपयोगी हो सकता है
      इससे जल्दी पता लगाया जा सकता है कि “किस PR ने bug introduce किया”, और उसके बाद उस branch में एक और detailed bisect चलाया जा सकता है
  • flaky test आने पर bisect सच में चमकता है
    जब race condition की वजह से भरोसा करने के लिए test को लाखों बार चलाना पड़े, तब bisect script को background में चलने देना व्यावहारिक समाधान बन जाता है

    • ऐसे मामलों में Bayesian binary search लगाने से शायद tests की संख्या काफ़ी कम की जा सकती है
  • हाल ही में Svelte से बने music player project(lets-make-sweet-music.com) में मैंने bisect से bug की वजह ढूँढी
    न tests थे, न error logs, और dependabot updates की वजह से commits बहुत हो गए थे, इसलिए trace करना मुश्किल था
    bisect की मदद से problematic commit मिल गया, और वजह यह थी कि मैंने जो file बदली थी उसमें event multi-binding feature implement नहीं था
    अगर commits छोटे रखे जाएँ, तो bisect से मिली समस्या की वजह को बहुत जल्दी सीमित किया जा सकता है

  • किसी ने कहा था कि interview में binary search सीखना ज़रूरत से ज़्यादा ज़ोर देकर पढ़ाया जाता है, लेकिन git bisect इस concept का एक बेहतरीन real-world example है
    हालाँकि इसे खुद implement करने की ज़रूरत नहीं होती। ज़्यादातर languages में यह standard library में पहले से मिलता है

    • दिलचस्प बात यह है कि binary search 1940 के दशक में पहली बार प्रस्तावित हुई थी, लेकिन bug-free implementation 1960 के दशक में जाकर सामने आई, ऐसी एक कहानी है
      middle index निकालते समय (low + high) / 2 करने पर overflow हो सकता है
    • मेरी निजी राय में हर developer को कम से कम एक बार arbitrary-precision integer language (जैसे Python) में binary search खुद implement करनी चाहिए
      यह invariant-based सोच की ट्रेनिंग के लिए बेहतरीन अभ्यास है
  • Git में bisect के अलावा log -L, log -S, blame जैसे शानदार code exploration tools भी हैं
    मैंने पहले इस विषय पर blog post भी लिखी थी