- बाइनरी सर्च (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 चलने की प्रक्रिया
निष्कर्ष
git bisect binary search के सिद्धांत को code history की खोज में लागू करने वाला एक व्यावहारिक tool है
- बड़े repository या जटिल बदलाव इतिहास में भी bug introduce होने के समय को तेज़ी से ट्रैक किया जा सकता है
- test automation के साथ मिलाकर बड़े codebase में भी स्थिर debugging संभव हो जाती है
2 टिप्पणियां
इन्हीं समस्याओं की वजह से हम TBD(trunk-based-develop) का इस्तेमाल करते हैं।
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 को और मज़बूत करता है
सीधे trace करना संभव नहीं था, लेकिन bisect script लिखकर करीब 30 मिनट चलाया और सही commit सटीक रूप से मिल गया
git bisectमूल रूप से Linux kernel regression ढूँढने के लिए लाया गया tool थाhardware driver जैसे मामलों में जहाँ test करना संभव नहीं होता, वहाँ भी आम user खुद kernel को bisect करके problematic commit की पहचान कर सकता था
पहले developers से email के ज़रिए मदद माँगनी पड़ती थी, लेकिन अब user खुद समस्या को सीमित कर सकता है
उदाहरण के लिए, गलत तरीके से process हुए data की सीमा trace करने में, या यह तय करने में कि “यह bug है या feature”, यह काफ़ी उपयोगी है
जैसे अगर कोई 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.ccommand से किसी खास function की change history trace करता हूँइसके लिए
.gitattributessetting चाहिए.gitattributessetting कैसी होनी चाहिए। उसे इस बारे में और जानने में दिलचस्पी थी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 में लिखी है
git bisect --first-parentउपयोगी हो सकता हैइससे जल्दी पता लगाया जा सकता है कि “किस PR ने bug introduce किया”, और उसके बाद उस branch में एक और detailed bisect चलाया जा सकता है
flaky test आने पर bisect सच में चमकता है
जब race condition की वजह से भरोसा करने के लिए test को लाखों बार चलाना पड़े, तब bisect script को background में चलने देना व्यावहारिक समाधान बन जाता है
हाल ही में Svelte से बने music player project(lets-make-sweet-music.com) में मैंने bisect से bug की वजह ढूँढी
न tests थे, न error logs, और
dependabotupdates की वजह से 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 में पहले से मिलता है
middle index निकालते समय
(low + high) / 2करने पर overflow हो सकता हैयह invariant-based सोच की ट्रेनिंग के लिए बेहतरीन अभ्यास है
Git में bisect के अलावा
log -L,log -S,blameजैसे शानदार code exploration tools भी हैंमैंने पहले इस विषय पर blog post भी लिखी थी