git bisect — Поиск ошибок
git bisect выполняет бинарный поиск по истории коммитов, чтобы найти точный коммит, который привнёс ошибку. Вместо проверки каждого коммита по одному, он каждый раз сокращает область поиска вдвое.
Почему бинарный поиск?
Если у вас 1000 коммитов, проверка каждого займёт до 1000 шагов. Бинарный поиск занимает максимум 10 шагов. В этом сила git bisect.
1000 коммитов → ~10 шагов
100 коммитов → ~7 шагов
50 коммитов → ~6 шагов
Как это работает
- Вы указываете Git один «хороший» коммит (где ошибки нет) и один «плохой» коммит (где она есть)
- Git переключается на коммит посередине между ними
- Вы тестируете и сообщаете Git, является ли этот коммит «хорошим» или «плохим»
- 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:
- Создайте репозиторий с серией коммитов:
git init && echo "working" > app.txt && git add app.txt && git commit -m "v1: working" - Добавьте ещё «хороших» коммитов:
echo "working v2" > app.txt && git add app.txt && git commit -m "v2: still working" echo "working v3" > app.txt && git add app.txt && git commit -m "v3: still working"- Привнесите «ошибку»:
echo "BROKEN" > app.txt && git add app.txt && git commit -m "v4: refactor" - Добавьте коммиты после ошибки:
echo "BROKEN v5" > app.txt && git add app.txt && git commit -m "v5: add feature" echo "BROKEN v6" > app.txt && git add app.txt && git commit -m "v6: more work"- Теперь найдите ошибку! Запустите bisect:
git bisect start - Пометьте текущий коммит как плохой:
git bisect bad - Пометьте первый коммит как хороший:
git bisect good HEAD~5 - Git переключится на средний коммит. Проверьте файл:
cat app.txt - Если в нём написано "working", выполните
git bisect good. Если "BROKEN", выполнитеgit bisect bad - Повторяйте шаги 10-11, пока Git не определит первый плохой коммит
- Завершите:
git bisect reset
Автоматический bisect
Вы можете автоматизировать bisect с помощью тестового скрипта:
git bisect start HEAD HEAD~20
git bisect run ./test.sh
Скрипт должен завершаться с кодом 0 для «хороших» и ненулевым кодом для «плохих» коммитов. Git найдёт виновника автоматически.
Советы
- Пишите хорошие сообщения коммитов — они помогают понять, что изменил каждый коммит при бисекции
- Делайте коммиты небольшими — бисекция, попавшая на коммит из 500 строк, сложнее для отладки, чем на коммит из 10 строк
- Используйте автоматические тесты —
git bisect runс тестовым скриптом — самый быстрый способ найти ошибки