Pro programátory

Git bisect mi ušetřil hodiny debugování

4. února 2026
12 min čtení
git bisectdebugginghledání bugůgitprogramováníregresegit diff

Pátek odpoledne, testy padají, nikdo neví proč. Poslední týden proběhlo 50 commitů od různých lidí. Kdo to rozbil?

Dřív bych checkoutoval commit po commitu a testoval. S git bisect to najdu za 7 kroků místo 50. Binární vyhledávání - půlím historii, dokud nenajdu viníka.

Kdy to používám

Hlavně na regrese - něco fungovalo a přestalo. Typicky:

  • Testy padají a "včera to šlo"
  • Výkon se zhoršil
  • Něco se chová jinak než dřív

Nehodí se když bug byl vždycky, nebo se projevuje náhodně (flaky testy).

Jak to používám v praxi

Celý postup je jednoduchý. Řeknu gitu kde je problém a kde byl naposledy klid:

git bisect start
git bisect bad            # aktuální stav je rozbitý
git bisect good v1.0.0    # tady to ještě fungovalo

Git mě hodí doprostřed historie:

Bisecting: 25 revisions left to test after this (roughly 5 steps)
[def5678] Fix: Update user validation logic

Teď spustím testy a řeknu výsledek:

git bisect good   # testy prošly
git bisect bad    # testy padly

Opakuju, dokud git nenajde viníka:

def5678 is the first bad commit
Author: Jan Novak <jan@example.com>

    Fix: Update user validation logic

A pak se podívám co se změnilo a ukončím session:

git show def5678           # co je v tom commitu
git diff def5678~1 def5678 # detailní změny
git bisect reset           # zpět na původní větev

Automatizace - to je ta pravá síla

Ručně označovat good/bad je otrava. Proto skoro vždy používám git bisect run:

git bisect start HEAD v1.0.0
git bisect run npm test

Git sám spouští testy a podle exit code pozná jestli je commit dobrý (0) nebo špatný (1-127). Exit code 125 znamená "přeskoč" - třeba když se nedá buildit.

Vlastní testovací skript

Když potřebuju něco složitějšího, napíšu si skript:

#!/bin/bash
# test-bug.sh

# Instalace závislostí (potřeba po checkout)
npm install --silent 2>/dev/null

# Build projektu
npm run build --silent 2>/dev/null

# Specifický test pro bug
npm test -- --grep "user validation" --silent

# Exit code určí good/bad
exit $?

Spuštění:

chmod +x test-bug.sh
git bisect start HEAD v1.0.0
git bisect run ./test-bug.sh

Na co jsem narazil

Build nefunguje na starých commitech - stává se. Prostě vrátím 125 a git to přeskočí:

#!/bin/bash
npm run build || exit 125
npm test

Závislosti se změnily - čistá instalace řeší:

#!/bin/bash
rm -rf node_modules
npm ci --silent
npm test

Různé Node verze - nvm zachrání:

#!/bin/bash
source ~/.nvm/nvm.sh
nvm use 2>/dev/null || nvm use default
npm test

Bisect + diff = debug combo

Najít commit je půlka práce. Teď potřebuju zjistit CO přesně se pokazilo.

Rozebírám commit

# Zobrazení commitu
git show def5678

# Zobrazení pouze změněných souborů
git show --stat def5678

# Detailní diff s kontextem
git show -p def5678

# Diff s více kontextu (10 řádků kolem změny)
git show -p -U10 def5678

Srovnám s předchozím stavem

git diff def5678~1 def5678                              # celý diff
git diff def5678~1 def5678 -- src/validators/user.ts   # jen jeden soubor
git diff --word-diff def5678~1 def5678                  # po slovech

Koukám do historie

git log --oneline --follow -- src/validators/user.ts   # kdo měnil soubor
git log -p -- src/validators/user.ts                   # s diffem
git blame -L 50,60 src/validators/user.ts              # kdo napsal tyto řádky

Pár triků navíc

Vlastní názvy místo good/bad

Někdy hledám kdy se něco ZLEPŠILO - třeba kdy se kód zrychlil. "Good" a "bad" pak nedávají smysl:

git bisect start --term-old=slow --term-new=fast
git bisect fast HEAD
git bisect slow v1.0.0

Uložení session

Když mě přeruší meeting, uložím si kde jsem:

git bisect log > bisect.log
# ...později...
git bisect replay bisect.log

Přeskakování commitů

Merge commity nebo rozbitý build? Skip:

git bisect skip                                  # přeskoč tento
git bisect skip abc1234..def5678                 # přeskoč rozsah
git bisect start --first-parent HEAD v1.0.0     # ignoruj merge commity

Vizualizace

Chci vidět co zbývá:

git bisect visualize    # otevře gitk
git bisect view --oneline   # textově

Reálný případ: DPH výpočet se rozbil

Tenhle příklad je z praxe. E-shop, ceny s DPH nefungují. Minulý týden (v2.3.0) to šlo.

# Spustím bisect
git bisect start
git bisect bad HEAD
git bisect good v2.3.0
# Bisecting: 23 revisions left to test (roughly 5 steps)

# Napíšu si testovací skript
cat > test-vat.sh << 'EOF'
#!/bin/bash
npm install --silent 2>/dev/null || exit 125
npm run build --silent 2>/dev/null || exit 125

# Test: cena 100 Kč s 21% DPH = 121 Kč
result=$(node -e "
  const { calculateVAT } = require('./dist/utils/price');
  console.log(calculateVAT(100, 0.21));
")

if [ "$result" = "121" ]; then
  exit 0  # good
else
  exit 1  # bad
fi
EOF

chmod +x test-vat.sh

# Pustím to
git bisect run ./test-vat.sh

# Za 5 kroků mám výsledek:
# abc7890 is the first bad commit
# Author: Pavel Svoboda
#     refactor: Simplify price calculations

# Podívám se co změnil
git show abc7890
git bisect reset

A problém byl jasný

Pomocí diff jsem viděl:

- return price * (1 + vatRate);
+ return price * vatRate;  // Bug: chybí základ ceny

Jednoduchá oprava:

// Správně
return price * (1 + vatRate);

Sdílení s týmem

Někdy potřebuju poslat kolegovi "hele, tady je ten bug":

git diff abc7890~1 abc7890 > changes.diff       # export do souboru
git diff abc7890~1 abc7890 | pbcopy             # rovnou do schránky (Mac)

Diff pak hodím do Code Diff pro barevné zobrazení, nebo pošlu link na GitHub:

gh browse abc7890   # otevře commit na GitHubu

Co mi pomáhá

Malé commity - čím menší, tím přesnější bisect:

# Tohle je k ničemu:
git commit -m "Various fixes and features"

# Tohle je super:
git commit -m "fix(price): Correct VAT calculation formula"

Každý commit musí jít buildit - jinak bisect skáče přes půlku historie.

Tagy na releases - pak vždycky vím kde hledat "good" commit:

git tag -a v2.3.0 -m "Release 2.3.0"

Git blame na doplnění - když už vím který soubor, blame mi ukáže kdo a kdy:

git blame src/utils/price.ts
# abc7890 (Pavel Svoboda 2026-01-15) return price * vatRate;

Chyby na které jsem narazil

"You need to start by git bisect start" - jo, zapomněl jsem git bisect start.

"No known good revision" - musím označit aspoň jeden dobrý commit přes git bisect good.

Zaseknutí na merge commitu - skip, nebo restart s --first-parent:

git bisect skip
# nebo
git bisect reset && git bisect start --first-parent HEAD v1.0.0

Flaky testy - to je nejhorší. Řeším opakováním:

#!/bin/bash
for i in {1..3}; do
  npm test && exit 0
done
exit 1

Když bisect nestačí

Někdy jdu jinou cestou:

Git log s grep - když vím co hledám:

git log -p -S "calculateVAT" --source --all   # kdo měnil tuhle funkci
git log --grep="VAT" --oneline                 # commity zmiňující VAT

Reflog - když jsem něco ztratil:

git reflog             # kde všude byl HEAD
git checkout HEAD@{5}  # vrať mě 5 kroků zpět

Pickaxe - kdy se objevila/zmizela funkce:

git log -p -S "function calculateVAT" -- "*.ts"

Shrnutí

Git bisect mi ušetřil hodiny práce. Místo procházení 50 commitů najdu problém za 7 kroků. S automatizací přes git bisect run to běží samo.

Hlavní je mít malé commity a buildovatelnou historii. Tagy na releases pomáhají najít výchozí bod.

A až najdete viníka, diff ukáže přesně co se pokazilo.


Potřebujete vizuálně porovnat změny v kódu po nalezení problematického commitu? Vyzkoušejte náš Code Diff nástroj – podporuje 22 programovacích jazyků a funguje přímo v prohlížeči.

Vyzkoušejte PorovnejText.cz zdarma

Nejrychlejší český nástroj pro porovnání textů. Vše probíhá ve vašem prohlížeči, žádná registrace není potřeba.

Porovnat texty nyní →