git bisect: jinsi ya kupata commit iliyovunja msimbo
git bisect hupata commit ambayo hitilafu ilianza kwa kutafuta kwa binary kwenye historia. Tekeleza git bisect start, weka alama ya commit mbaya kwa git bisect bad na commit inayojulikana kufanya kazi kwa git bisect good <hash>, kisha hakiki commits zinazopendekezwa hadi Git itakapotaja mhusika; mwishoni tumia git bisect reset.
git bisect inatafuta commit iliyoleta hitilafu kwa njia ya utafutaji wa binary. Unaonyesha commit moja ambapo hitilafu ipo, na moja ambapo haikuwepo — Git inakupeleka katikati ya safu na kuuliza: «hapa ni sawa au ni mbaya?». Kila jibu linaondoa nusu ya wagombea, kwa hiyo kati ya commits 1000 mhusika hupatikana kwa takriban ukaguzi 10.
Hii ni muhimu hasa pale hitilafu isipoonekana wazi: jaribio limeshindwa, utendaji umeshuka, mpangilio wa kurasa umevurugika, lakini tofauti za mabadiliko hazieleweki. Badala ya kusoma mamia ya mabadiliko, unauliza swali lile lile rahisi mara kadhaa.
Utafutaji wa binary kwenye historia unavyofanya kazi
Tuseme kati ya toleo linalofanya kazi v2.3 na main ya sasa kuna commits 200. Git inachukua commit ya katikati na kuikagua. Ikiwa tayari imevunjika, hitilafu ilianza nusu ya kwanza; ikiwa haijavunjika, ilianza nusu ya pili. Idadi ya wagombea inapungua kwa nusu kila hatua: 200, 100, 50, 25, 13, 7, 4, 2, 1. Ukaguzi nane badala ya mia mbili.
Hapa ndipo sharti kuu lipo: hali ya «imevunjika» lazima iwe ya monotonic. Ikiwa hitilafu ilionekana, ikatoweka, kisha ikarudi, bisect itapata mojawapo ya mabadiliko, lakini si lazima lile unalohitaji.
git bisect hatua kwa hatua: hali ya mkono
1. Tafuta commit nzuri na mbaya
Mbaya kwa kawaida ni HEAD ya sasa. Nzuri ni commit yoyote ambapo kila kitu hakika kilifanya kazi: tagi ya toleo lililopita, commit ya wiki iliyopita. Kukusaidia kupata wagombea, tumia git log --oneline, git tag au git log --since="2 weeks ago".
2. Anza kikao
git bisect start
git bisect bad # commit ya sasa imevunjika
git bisect good v2.3 # kwenye toleo v2.3 kila kitu kilifanya kazi
Bisecting: 99 revisions left to test after this (roughly 7 steps)
[4f5e6d7c...] Sasisha utegemezi za frontend
Hilo hilo linaweza kuandikwa kwa mstari mmoja: git bisect start HEAD v2.3 — kwanza mbaya, kisha nzuri. Git mara moja inabadilisha saraka ya kazi kwenda commit ya katikati (katika hali ya detached HEAD).
3. Kagua na weka alama
Jenga mradi, endesha jaribio au uzalishe hitilafu kwa mkono. Kisha toa matokeo:
git bisect good # hapa inafanya kazi
Bisecting: 49 revisions left to test after this (roughly 6 steps)
git bisect bad # hapa imevunjika
Bisecting: 24 revisions left to test after this (roughly 5 steps)
4. Pata matokeo
Wakati mgombea mmoja tu anabaki, Git inautoa:
a1b2c3d4e5f6... is the first bad commit
commit a1b2c3d4e5f6...
Author: Ivan Petrov <ivan@example.com>
Date: Tue Sep 29 11:40:12 2026 +0300
Hifadhi matokeo ya hesabu ya kikapu kwenye cache
src/cart.js | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
5. Funga kikao
git bisect reset
Amri hii inakurudisha kwenye tawi ulilokuwa ukifanyia kazi. Usisahau hatua hii: mradi kikao hakijafungwa, utabaki kwenye detached HEAD, na commits mpya zinaweza kupotea kwa urahisi. Chaguo git bisect reset HEAD litakubakiza kwenye commit uliyoipata, na git bisect reset <commit> — kwenye commit yoyote uliyoitaja.
Utafutaji wa kiotomatiki: git bisect run
Ikiwa ukaguzi unaweza kuelezwa kwa amri, kabidhi kazi yote kwa Git. git bisect run huendesha script kwenye kila hatua na yenyewe huweka alama kwa kutumia msimbo wa kutoka:
| Msimbo wa kutoka | Maana yake |
|---|---|
| 0 | good — commit ni nzuri |
| 1–127, isipokuwa 125 | bad — commit ni mbaya |
| 125 | skip — commit haiwezi kukaguliwa, ruka |
| zaidi ya 127 (au <0) | simamisha bisect (kwa mfano script imeanguka kwa ishara) |
Mifano ya kuendesha:
git bisect start HEAD v2.3
git bisect run npm test
git bisect run pytest tests/test_cart.py -x
git bisect run make check
Kwa ukaguzi tata, andika script ndogo. Ni muhimu kutenganisha «haikujengwa» na «hitilafu imejitokeza», vinginevyo bisect itachukulia ujenzi uliovunjika kuwa ndio hitilafu unayoitafuta:
#!/bin/sh
# check.sh
npm ci --silent || exit 125 # utegemezi haukuweza kusakinishwa — ruka
npm run build || exit 125 # haikujengwa — ruka
node scripts/check-cart-total.js # 0 — sawa, 1 — hitilafu
chmod +x check.sh
git bisect run ./check.sh
Weka script nje ya faili zinazofuatiliwa, au kwenye folda iliyopo kwenye commits zote zinazokaguliwa: bisect inabadilisha saraka ya kazi, na faili iliyoongezwa hivi karibuni itatoweka kwenye commits za zamani. Njia salama zaidi ni kuiweka /tmp au folda yoyote nje ya hifadhi.
Jaribio ambalo halikuwepo zamani
Hali ya kawaida: umeandika jaribio linaloonyesha hitilafu, lakini kwenye commits za zamani faili hiyo haipo. Suluhisho ni nakala ile ile nje ya hifadhi:
cp tests/test_regression.py /tmp/
git bisect run pytest /tmp/test_regression.py
git bisect skip: commit isiyoweza kukaguliwa
Wakati mwingine commit iliyo katikati haijengwi au inaanguka kwa sababu nyingine. Huwezi kuiweka alama good wala bad — hiyo ingepotosha matokeo. Ruka:
git bisect skip
git bisect skip v2.4..v2.4.3 # ruka safu nzima
Git itachagua commit jirani. Ikiwa commits zilizorukwa zipo kwenye mpaka kabisa, mwishoni utaona orodha ya «wahusika wanaowezekana» badala ya mmoja — basi kagua diff zao kwa mkono.
Maneno yako badala ya good na bad
Bisect haitafuti hitilafu pekee. Kwa mfano, unataka kupata commit baada ya ukurasa kuanza kupakia haraka. Kuita commits za haraka «mbaya» kunachanganya, kwa hiyo kuna maneno mbadala:
git bisect start --term-old=slow --term-new=fast
git bisect fast HEAD
git bisect slow v2.3
Visawe vilivyojengwa ndani ni old na new: git bisect new, git bisect old. Kanuni moja: hali ya «zamani» lazima iwe kwenye commit ya awali zaidi.
Kumbukumbu ya kikao: log, replay, visualize
git bisect log— inaonyesha alama zako zote. Ihifadhi kwenye faili ikiwa kikao ni kirefu.git bisect replay faili— inarudia kikao kwa kutumia kumbukumbu. Ulikosea hatua ya sita? Hifadhi log, futa mistari isiyo sahihi, tekelezagit bisect resetnareplay.git bisect visualize(augit bisect view) — inaonyesha wagombea waliobaki; kwa--onelineinawaonyesha kupitia git log.
git bisect log > /tmp/bisect.log
# hariri log
git bisect reset
git bisect replay /tmp/bisect.log
Bisect na merge commits
Kwenye historia yenye merges nyingi, bisect inaweza kukupeleka ndani ya tawi lililounganishwa — kwenye commits zilizoundwa kabla tawi halijasawazishwa na main, hivyo zikijengwa kwenye msingi tofauti. Ikiwa unataka kwanza kuelewa ni merge ipi iliyoleta hitilafu, tumia:
git bisect start --first-parent
Hapo Git inapita tu kwenye wazazi wa kwanza wa merge commits, yaani kwenye historia ya tawi kuu. Baada ya kupata merge yenye hatia, unaweza kuendesha bisect ya pili ndani ya tawi husika.
Makosa ya kawaida
- Umechanganya good na bad. Matokeo yatakuwa hayana maana. Rejesha kikao kwa
git bisect lognareplay, bila kuanza upya. - Saraka ya kazi chafu. Mabadiliko ambayo hayajawekwa commit yanavuruga ubadilishaji wa commits na yanaathiri ukaguzi. Kabla ya kuanza, weka commit au tumia
git stash. - Mabaki ya ujenzi hayajasafishwa. Cache ya zamani au
node_moduleskutoka commit nyingine zinatoa matokeo ya uongo. Kwenye script fanya ujenzi safi. - Jaribio lisilo thabiti (flaky). Ikiwa jaribio wakati mwingine linashindwa lenyewe, bisect itaweka alama commit isiyohusika. Endesha ukaguzi mara kadhaa au rekebisha jaribio kabla ya kutafuta.
- Umesahau reset. Umebaki kwenye detached HEAD na umeanza kazi. Commits zilizopotea zinaweza kupatikana kwenye reflog.
Mfano: kutafuta regression kutoka mwanzo hadi mwisho
Watumiaji walisema kwamba jumla ya kikapu inahesabiwa vibaya wakati wa punguzo. Kwenye toleo v2.3 kila kitu kilikuwa sahihi, kwenye main hakipo. Tunaandika ukaguzi mdogo na kuendesha utafutaji:
cat > /tmp/check.sh <<'SH'
#!/bin/sh
npm ci --silent || exit 125
node -e "const c=require('./src/cart'); process.exit(c.total([{price:100}], 0.1) === 90 ? 0 : 1)"
SH
chmod +x /tmp/check.sh
git stash # ondoa mabadiliko ambayo hayajawekwa commit
git bisect start HEAD v2.3
git bisect run /tmp/check.sh
...
a1b2c3d4e5f6... is the first bad commit
git bisect log > /tmp/cart-bisect.log
git bisect reset
git stash pop
Utafutaji wote kwenye commits mia moja unaendelea bila wewe, wakati unashughulikia mambo mengine. Kumbukumbu iliyohifadhiwa itakusaidia ikiwa unahitaji kuonyesha wenzako jinsi mhusika alivyopatikana.
Cha kufanya na commit iliyopatikana
Mhusika akishapatikana, angalia commit nzima: git show a1b2c3d. Commit ndogo yenye ujumbe ulio wazi itakupa sababu mara moja — hii ni moja ya sababu timu zinathamini commits za atomiki: bisect kwenye historia iliyojaa «fix stuff» karibu haina msaada. Baadaye una njia mbili: kurekebisha hitilafu kwa commit mpya, au, ikiwa mabadiliko yote hayakufaa na tayari yametumwa, kuyaghairi kwa git revert a1b2c3d.
Muhtasari
git bisect hubadilisha utafutaji wa regression kutoka kusoma mamia ya diffs kuwa majibu machache ya «inafanya kazi / haifanyi kazi», na kwa git bisect run kuwa amri moja. Unahitaji alama mbili tu — commit nzuri na mbaya — na ukaguzi unaorudiwa kwa uhakika. Kusoma historia, kusogeza kati ya commits na kutafuta hitilafu ndani yake vimefafanuliwa kwa vitendo katika kozi ya Git.
Maswali ya mara kwa mara
git bisect itachukua hatua ngapi?
Takriban log2 ya idadi ya commits kwenye safu: karibu hatua 7 kwa commits 100 na karibu 10 kwa commits 1000. Git yenyewe inaonyesha makadirio ya roughly N steps.
Je, inawezekana kuendesha bisect bila kujua commit nzuri?
Unahitaji angalau moja. Chukua commit ya zamani sana au tagi ya toleo na uikague kwa mkono; hatua chache za ziada kwa sababu ya safu pana hazina gharama kubwa.
Je, git bisect hubadilisha historia ya hifadhi?
Hapana, inabadilisha tu saraka ya kazi kati ya commits na kuhifadhi alama kwenye marejeo ya ndani refs/bisect, ambayo yanafutwa kwa git bisect reset.
Je, naweza kutaja commits nyingi nzuri?
Ndiyo, amri ya git bisect good inaweza kupokea commits kadhaa, jambo linalopunguza safu, hasa kwenye historia yenye matawi mengi.
Je, bisect inafanya kazi kutafuta hitilafu tu?
Hapana, inaweza kupata wakati wowote mali ilipobadilika: faili ilipoonekana, ujenzi ulipoharakishwa au tabia ilipobadilika. Kwa hilo, maneno old/new au yako mwenyewe kupitia --term-old na --term-new ni rahisi.
Mada hii inafundishwa kwa kina pamoja na mazoezi katika kozi “Git kutoka mwanzo hadi msanidi programu anayejiweza”.
Nenda kwenye kozi