Gabay

git bisect: paano hanapin ang commit na sumira sa code

Na-update: · Skillaria.Top

Hinahanap ng git bisect ang commit kung saan lumitaw ang error sa pamamagitan ng binary search sa history. Patakbuhin ang git bisect start, markahan ang sirang commit gamit ang git bisect bad at ang gumaganang commit gamit ang git bisect good <hash>, tapos suriin ang mga iminumungkahing commit hanggang pangalanan ng Git ang salarin; sa dulo, git bisect reset.

git bisect ang naghahanap ng commit na nagpasok ng error, gamit ang binary search. Itinuturo ninyo ang isang commit kung saan may bug at isa kung saan wala pa ito. Ililipat kayo ng Git sa gitna ng saklaw at magtatanong: "okay ba rito o sira?" Bawat sagot ay nagtatanggal ng kalahati ng kandidato, kaya sa 1000 commit, mahahanap ang salarin sa humigit-kumulang 10 na pagsusuri.

Lalo itong mahalaga kapag hindi halata ang error: bumagsak ang test, bumagal ang performance, nagulo ang layout, pero walang makitang kahulugan sa mga diff. Sa halip na basahin ang daan-daang pagbabago, itatanong ninyo ang iisang simpleng tanong nang ilang beses.

Paano gumagana ang binary search sa history

Ipagpalagay na may 200 commit sa pagitan ng gumaganang bersyon na v2.3 at ng kasalukuyang main. Kukunin ng Git ang commit sa gitna at susuriin ito. Kung sira na roon, lumitaw ang error sa unang kalahati; kung hindi, sa ikalawang kalahati. Nababawasan ng kalahati ang mga kandidato sa bawat hakbang: 200, 100, 50, 25, 13, 7, 4, 2, 1. Walong pagsusuri lang, imbes na dalawang daan.

Dito nakasalalay ang pangunahing kondisyon: dapat monotonic ang katangiang "sira". Kung lumitaw ang bug, nawala, at bumalik, makikita ng bisect ang isa sa mga transisyon, pero hindi kinakailangang ang gusto ninyo.

git bisect hakbang-hakbang: manual na mode

1. Hanapin ang gumaganang at sirang commit

Ang sira ay karaniwang kasalukuyang HEAD. Ang gumagana ay anumang commit kung saan siguradong gumana ang lahat: tag ng nakaraang release, o commit ng nakaraang linggo. Makakatulong dito ang git log --oneline, git tag, o git log --since="2 weeks ago".

2. Simulan ang session

git bisect start
git bisect bad                 # sira ang kasalukuyang commit
git bisect good v2.3           # gumana ang lahat sa release v2.3
Bisecting: 99 revisions left to test after this (roughly 7 steps)
[4f5e6d7c...] Update frontend dependencies

Pareho ito sa isang linya: git bisect start HEAD v2.3, una ang sira, tapos ang gumagana. Agad na inilipat ng Git ang working directory sa commit sa gitna (sa estadong detached HEAD).

3. Subukan at markahan

I-build ang project, patakbuhin ang test, o i-reproduce nang manwal ang bug. Pagkatapos, sabihin ang resulta:

git bisect good     # gumagana rito
Bisecting: 49 revisions left to test after this (roughly 6 steps)

git bisect bad      # sira rito
Bisecting: 24 revisions left to test after this (roughly 5 steps)

4. Kunin ang resulta

Kapag iisa na lang ang kandidato, ilalabas ito ng Git:

a1b2c3d4e5f6... is the first bad commit
commit a1b2c3d4e5f6...
Author: Juan Dela Cruz <juan@example.com>
Date:   Tue Sep 29 11:40:12 2026 +0800

    Cache ang resulta ng kuwenta ng cart

 src/cart.js | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

5. Tapusin ang session

git bisect reset

Ibabalik kayo ng command sa branch na pinanggalingan ninyo. Huwag kalimutan ang hakbang na ito: hangga't hindi nagsasara ang session, nasa detached HEAD kayo, at madaling mawala ang mga bagong commit. Ang git bisect reset HEAD ay mananatili sa nahanap na commit, at ang git bisect reset <commit> ay sa anumang tinukoy na commit.

Awtomatikong paghahanap: git bisect run

Kung maipapahayag ang pagsusuri bilang command, ipagawa na sa Git ang lahat. Pinapatakbo ng git bisect run ang script sa bawat hakbang at siya na ang nagmamarka base sa exit code:

Exit codeIbig sabihin
0good: maayos ang commit
1–127, maliban sa 125bad: sira ang commit
125skip: hindi masusuri ang commit, laktawan
Mas mataas sa 127 (o <0)itigil ang bisect (halimbawa, bumagsak ang script dahil sa signal)

Mga halimbawa ng pagpapatakbo:

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

Para sa mas komplikadong pagsusuri, gumawa ng maliit na script. Mahalagang paghiwalayin ang "hindi nag-build" sa "na-reproduce ang bug", kung hindi, mapagkakamalang target ng bisect ang sirang build:

#!/bin/sh
# check.sh
npm ci --silent || exit 125      # hindi na-install ang dependencies, laktawan
npm run build   || exit 125      # hindi nag-build, laktawan
node scripts/check-cart-total.js # 0 = ok, 1 = bug
chmod +x check.sh
git bisect run ./check.sh

Panatilihin ang script sa labas ng mga tinatrack na file, o sa folder na nasa lahat ng sinusuring commit: inililipat ng bisect ang working directory, kaya mawawala sa lumang commit ang file na kamakailan lang idinagdag. Pinakaligtas na ilagay ito sa /tmp o sa anumang folder sa labas ng repository.

Test na wala pa noon

Karaniwang sitwasyon: sumulat kayo ng test na nag-re-reproduce ng bug, pero wala ang file na iyon sa mga lumang commit. Ang solusyon ay kopyahin ito sa labas ng repository:

cp tests/test_regression.py /tmp/
git bisect run pytest /tmp/test_regression.py

git bisect skip: kapag hindi masusuri ang commit

Minsan, ang commit sa gitna ay hindi nag-build o bumabagsak dahil sa ibang dahilan. Hindi ninyo ito puwedeng markahan bilang good o bad, dahil masisira ang resulta. Laktawan ito:

git bisect skip
git bisect skip v2.4..v2.4.3   # laktawan ang saklaw

Pipiliin ng Git ang katabing commit. Kung ang mga nilaktawang commit ay nasa mismong hangganan, sa dulo ay makakakita kayo ng listahan ng "posibleng salarin" imbes na iisa; saka ninyo tingnan nang manwal ang kanilang mga diff.

Sariling mga termino sa halip na good at bad

Hindi lang bug ang hinahanap ng bisect. Halimbawa, gusto ninyong hanapin ang commit pagkatapos nito bumilis ang pag-load ng page. Hindi maganda pakinggan na tawaging "bad" ang mga mabilis na commit, kaya may alternatibong salita:

git bisect start --term-old=slow --term-new=fast
git bisect fast HEAD
git bisect slow v2.3

Built-in na kasingkahulugan ang old at new: git bisect new, git bisect old. Iisa ang tuntunin: ang "lumang" estado ay dapat nasa mas naunang commit.

Log ng session: log, replay, visualize

  • git bisect log: ipinapakita ang lahat ng marka ninyo. I-save sa file kung mahaba ang session.
  • git bisect replay file: inuulit ang session ayon sa log. Nagkamali kayo sa ikaanim na hakbang? I-save ang log, tanggalin ang maling linya, patakbuhin ang git bisect reset at replay.
  • git bisect visualize (o git bisect view): ipinapakita ang natitirang kandidato; kapag may --oneline, ipinapakita ang mga ito sa pamamagitan ng git log.
git bisect log > /tmp/bisect.log
# i-edit ang log
git bisect reset
git bisect replay /tmp/bisect.log

Bisect at merge commits

Sa history na maraming merge, maaaring dalhin kayo ng bisect sa loob ng na-merge na branch, sa mga commit na ginawa bago pa ito i-sync sa main, kaya nakabatay sila sa ibang base. Kung gusto ninyong unahing alamin kung aling merge ang nagdala ng bug, gamitin ito:

git bisect start --first-parent

Sa ganitong paraan, dumadaan lang ang Git sa unang parent ng merge commits, ibig sabihin, sa history ng pangunahing branch. Kapag nahanap na ang merge na may kasalanan, puwede ninyong patakbuhin ang pangalawang bisect sa loob ng kaukulang branch.

Karaniwang pagkakamali

  • Napalitan ang good at bad. Walang saysay ang resulta. Ibalik ang session gamit ang git bisect log at replay, huwag nang magsimula ulit.
  • Maruming working directory. Nakakasagabal sa paglipat ng commit ang mga hindi pa naka-commit na pagbabago at nakakaapekto ito sa pagsusuri. Bago magsimula, mag-commit o gumamit ng git stash.
  • Hindi nilinis na build artifacts. Ang lumang cache o node_modules mula sa ibang commit ay nagbibigay ng maling resulta. Gumamit ng malinis na build sa script.
  • Flaky na test. Kapag minsan lang bumagsak ang test nang mag-isa, mamarkahan ng bisect ang random na commit. Patakbuhin ang pagsusuri nang ilang beses, o ayusin muna ang test bago maghanap.
  • Nakalimutang reset. Naiwan kayo sa detached HEAD at nagsimula ng trabaho. Makakatulong ang reflog sa paghanap ng nawalang commit.

Halimbawa: paghahanap ng regression mula simula hanggang dulo

May nag-report na mali ang kuwenta ng kabuuan ng cart kapag may diskuwento. Tama ito sa release v2.3, pero mali sa main. Gagawa tayo ng minimal na pagsusuri at patatakbuhin ang paghahanap:

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                       # itabi ang mga hindi pa naka-commit na edit
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

Tumatakbo ang buong paghahanap sa mahigit isandaang commit nang hindi kayo kailangan, habang ginagawa ninyo ang iba. Kapaki-pakinabang ang na-save na log kung kailangang ipakita sa mga katrabaho kung paano natagpuan ang salarin.

Ano ang gagawin sa nahanap na commit

Kapag nahanap na ang salarin, tingnan itong buo: git show a1b2c3d. Maliit na commit na may malinaw na mensahe ang agad na magsasabi ng dahilan. Ito ang isa sa mga dahilan kung bakit pinahahalagahan sa team ang atomic commits: halos walang silbi ang bisect sa history na puno ng "fix stuff" na malalaking commit. May dalawang daan pagkatapos: ayusin ang error sa pamamagitan ng bagong commit, o, kung talagang mali ang buong pagbabago at naipadala na, i-undo ito gamit ang git revert a1b2c3d.

Buod

Ginagawang ilang sagot na "gumagana / hindi gumagana" ang paghahanap ng regression ng git bisect, at sa git bisect run, ginagawa itong iisang command. Dalawang reference lang ang kailangan: isang magandang commit at isang sirang commit, at isang pagsusuring maaaring ulitin. Ang pagbabasa ng history, pag-navigate sa mga commit, at paghahanap ng bug dito ay itinuturo nang praktikal sa kursong Git namin.

Mga madalas itanong

Ilang hakbang ang gagawin ng git bisect?

Humigit-kumulang log2 ng bilang ng commit sa saklaw: mga 7 hakbang para sa 100 commit at mga 10 para sa 1000. Ipinapakita rin ng Git ang tantiya bilang roughly N steps.

Puwede bang simulan ang bisect kung hindi ko alam ang gumaganang commit?

Kailangan ng kahit isa. Pumili ng lumang commit o tag ng release at suriin ito nang manwal; ang dagdag na hakbang dahil sa malawak na saklaw ay halos walang bigat.

Binabago ba ng git bisect ang history ng repository?

Hindi, inililipat lang nito ang working directory sa pagitan ng mga commit, at iniimbak ang mga marka sa mga internal reference na refs/bisect na nabubura sa git bisect reset.

Puwede bang magbigay ng maraming gumaganang commit?

Oo, maaaring magbigay ng maraming commit sa git bisect good, na nagpapaliit ng saklaw, lalo na sa history na may maraming branch.

Para lang ba sa paghahanap ng bug ang bisect?

Hindi, magagamit ito para hanapin ang anumang punto kung kailan nagbago ang isang katangian: kailan lumitaw ang file, kailan bumilis ang build, o kailan nagbago ang kilos. Para dito, kapaki-pakinabang ang old/new o sariling termino gamit ang --term-old at --term-new.

Pag-aralan ito sa video

Detalyadong tinatalakay ang paksang ito, may praktis, sa kursong “Git с нуля до уверенного разработчика”.

Pumunta sa kurso