linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
Intro
Lessons
Footer
linuxlab-TutorialsPricingAboutPrivacy & cookies
Copyright © 2026 LinuxLab. All rights reserved.
linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
  • Introduction
  • Chapters
  • How it works
  • Lessons
  • Knowledge base
  • Interview prep
home/git/lessons/git-lab-10-1-bisect

lesson ── git-labs ── ~18 мин ── 7 шагов

git bisect: find a bug with binary search

The goal is to find the exact commit that broke a behavior without reading through the whole history by hand. git bisect does a binary search: you say "it worked here", "it is broken here", Git halves the interval, you test, you repeat. log(n) steps instead of n.

▶ интерактивный sandbox

Поднимется контейнер gitlab/git-base с git, bash, pre-commit. В браузере откроется терминал, можно сразу git init. Каждый шаг проверяется автоматически. Сеть air-gapped, github.com недоступен.

запустить sandbox →

stack ── git · bash · 256 MB RAM · air-gapped · самоуничтожается через 30 мин простоя

Шаги

  1. 01

    Create a repo with 10 commits, one of which breaks the behavior

    bash
    cd /home/student/work
    mkdir -p bisect-lab && cd bisect-lab
    git init -b main
    cat > app.sh <<'EOF'
    #!/bin/bash
    echo "ok"
    EOF
    chmod +x app.sh
    git add . && git commit -m "init: working app"
    for i in 1 2 3 4; do
      echo "# noop change $i" >> app.sh   # noise commits before the broken one
      git commit -am "tweak $i"
    done
    # the breaking commit: change output from "ok" to "fail" via sed -i (in place)
    sed -i 's/echo "ok"/echo "fail"/' app.sh
    git commit -am "refactor: tune output"
    for i in 5 6 7 8 9; do
      echo "# more noop $i" >> app.sh     # noise commits after the broken one
      git commit -am "tweak $i (later)"
    done
    git log --oneline | wc -l     # should print 10

    10 commits. One of them broke the output. Which one is unknown for now.

    ✓ 10 commits, current output is 'fail'. You need to find which commit is to blame.

  2. 02

    Confirm that HEAD is broken and the first commit works

    bash
    cd /home/student/work/bisect-lab
    ./app.sh                      # current output: fail
    git stash 2>/dev/null         # set local changes aside just in case
    # --max-parents=0 = a commit with no parent, the root (init)
    FIRST=$(git rev-list --max-parents=0 HEAD)
    git checkout $FIRST -- app.sh # pull app.sh from the init commit into the working tree
    ./app.sh                      # output "ok": confirms that init worked
    git checkout HEAD -- app.sh   # restore the current (broken) version

    The first commit gives ok. HEAD gives fail. The search starts on the interval "between them".

    ✓ HEAD is broken, init works. Start bisect.

  3. 03

    Start bisect by hand

    bash
    cd /home/student/work/bisect-lab
    git bisect start              # turn on search mode
    git bisect bad HEAD           # the current commit is broken
    FIRST=$(git rev-list --max-parents=0 HEAD)
    git bisect good $FIRST        # the root commit worked

    Git jumps to the middle of the interval and says something like Bisecting: 4 revisions left to test after this (roughly 2 steps). That is binary search in action.

    ✓ Bisect is running. Git picked the commit in the middle.

  4. 04

    Take one bisect step by hand

    Check the current commit:

    bash
    cd /home/student/work/bisect-lab
    ./app.sh

    If you see ok, the current commit is good: git bisect good. If fail, it is bad: git bisect bad. Act on the result:

    bash
    # grep -q = quiet (exit code only); ok found = good, otherwise bad
    ./app.sh | grep -q ok && git bisect good || git bisect bad

    Git picks the next commit to check.

    ✓ You took one step. The interval shrank by half.

  5. 05

    Finish bisect to the end (or stop it)

    You can keep going by hand (./app.sh && git bisect good/bad a few times), but it is simpler to switch to the automatic search with bisect run. First leave the current one:

    bash
    cd /home/student/work/bisect-lab
    git bisect reset

    This returns HEAD to main.

    ✓ Bisect stopped. Next, the automatic search.

  6. 06

    Write a test script for the auto search

    git bisect run expects a script that returns 0 for a good commit and 1 for a bad one.

    bash
    cd /home/student/work/bisect-lab
    # test: exit 0 if the output has "ok", exit 1 if not
    cat > test.sh <<'EOF'
    #!/bin/bash
    ./app.sh | grep -q ok
    EOF
    chmod +x test.sh
    ./test.sh && echo "exit 0 (good)" || echo "exit 1 (bad)"

    On HEAD it prints exit 1 (bad). That is expected.

    ✓ The test script works. Start the automatic search.

  7. 07

    Run the automatic search with bisect run

    bash
    cd /home/student/work/bisect-lab
    # bisect start <bad> <good> = set the bounds right away
    git bisect start HEAD $(git rev-list --max-parents=0 HEAD)
    git bisect run ./test.sh      # auto run: runs test.sh at each step

    Git jumps over several commits, runs test.sh for each one, and reports: <sha> is the first bad commit. The commit message should be refactor: tune output, the very one where we replaced ok with fail.

    Leave bisect:

    bash
    git bisect reset

    ✓ The automatic bisect found the culprit. log(n) against n.

Что ты узнал

bisect halves the interval of commits, you mark the good ones and the bad ones. When you can check automatically, bisect run does everything for you.

команды

  • git bisect startstart the search
  • git bisect badthe current commit is bad
  • git bisect good <sha>point to a good base
  • git bisect run ./test.shauto search with a script
  • git bisect resetleave search mode

концепции

  • · bisect is a binary search through history
  • · you must be able to automate the criterion: a script with an exit code
  • · exit 0 = good, exit 1 = bad, exit 125 = skip

← предыдущая

Undoing: reset, revert, reflog

следующая →

Trunk-based: features behind flags in main

Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies