Mwongozo

git bisect: jinsi ya kupata commit iliyovunja msimbo

Imesasishwa: · Skillaria.Top

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 kutokaMaana yake
0good — commit ni nzuri
1–127, isipokuwa 125bad — commit ni mbaya
125skip — 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, tekeleza git bisect reset na replay.
  • git bisect visualize (au git bisect view) — inaonyesha wagombea waliobaki; kwa --oneline inawaonyesha 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 log na replay, 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_modules kutoka 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.

Jifunze mada hii kwa video

Mada hii inafundishwa kwa kina pamoja na mazoezi katika kozi “Git kutoka mwanzo hadi msanidi programu anayejiweza”.

Nenda kwenye kozi