Тур по Git
Продвинутый Git / Урок 5.4

git bisect — Поиск ошибок

git bisect выполняет бинарный поиск по истории коммитов, чтобы найти точный коммит, который привнёс ошибку. Вместо проверки каждого коммита по одному, он каждый раз сокращает область поиска вдвое.

Почему бинарный поиск?

Если у вас 1000 коммитов, проверка каждого займёт до 1000 шагов. Бинарный поиск занимает максимум 10 шагов. В этом сила git bisect.

1000 коммитов → ~10 шагов
100 коммитов  → ~7 шагов
50 коммитов   → ~6 шагов

Как это работает

  1. Вы указываете Git один «хороший» коммит (где ошибки нет) и один «плохой» коммит (где она есть)
  2. Git переключается на коммит посередине между ними
  3. Вы тестируете и сообщаете Git, является ли этот коммит «хорошим» или «плохим»
  4. Git сужает диапазон и повторяет
good ——— ? ——— ? ——— ? ——— ? ——— bad
                ↓
good ——— ? ——— [тестируем этот] ——— ? ——— bad
                ↓ (bad)
good ——— [тестируем этот] ——— bad
                ↓ (good)
good ——— [ЭТОТ КОММИТ ПРИВНЁС ОШИБКУ] ——— bad

Основные команды

git bisect start          # начать бисекцию
git bisect bad            # пометить текущий коммит как плохой
git bisect good abc1234   # пометить известный хороший коммит
# Git переключается на средний коммит...
git bisect good           # если этот коммит работает
git bisect bad            # если этот коммит сломан
# Повторяйте, пока Git не найдёт виновника
git bisect reset          # завершить и вернуться к исходной ветке

Попробуйте!

Потренируйтесь находить ошибку с помощью bisect:

  1. Создайте репозиторий с серией коммитов: git init && echo "working" > app.txt && git add app.txt && git commit -m "v1: working"
  2. Добавьте ещё «хороших» коммитов: echo "working v2" > app.txt && git add app.txt && git commit -m "v2: still working"
  3. echo "working v3" > app.txt && git add app.txt && git commit -m "v3: still working"
  4. Привнесите «ошибку»: echo "BROKEN" > app.txt && git add app.txt && git commit -m "v4: refactor"
  5. Добавьте коммиты после ошибки: echo "BROKEN v5" > app.txt && git add app.txt && git commit -m "v5: add feature"
  6. echo "BROKEN v6" > app.txt && git add app.txt && git commit -m "v6: more work"
  7. Теперь найдите ошибку! Запустите bisect: git bisect start
  8. Пометьте текущий коммит как плохой: git bisect bad
  9. Пометьте первый коммит как хороший: git bisect good HEAD~5
  10. Git переключится на средний коммит. Проверьте файл: cat app.txt
  11. Если в нём написано "working", выполните git bisect good. Если "BROKEN", выполните git bisect bad
  12. Повторяйте шаги 10-11, пока Git не определит первый плохой коммит
  13. Завершите: git bisect reset

Автоматический bisect

Вы можете автоматизировать bisect с помощью тестового скрипта:

git bisect start HEAD HEAD~20
git bisect run ./test.sh

Скрипт должен завершаться с кодом 0 для «хороших» и ненулевым кодом для «плохих» коммитов. Git найдёт виновника автоматически.

Советы

  • Пишите хорошие сообщения коммитов — они помогают понять, что изменил каждый коммит при бисекции
  • Делайте коммиты небольшими — бисекция, попавшая на коммит из 500 строк, сложнее для отладки, чем на коммит из 10 строк
  • Используйте автоматические тесты — git bisect run с тестовым скриптом — самый быстрый способ найти ошибки
🎯

Цель

Используйте git bisect для поиска коммита, который внёс ошибку

Terminal
$

No commits yet. Run `git init` and create your first commit.