


git bisect помогает найти изменение, после которого появился воспроизводимый дефект. Вы задаёте исправную и сломанную версии, проверяете предложенные Git коммиты и постепенно сужаете диапазон. Самая важная часть работы здесь: одинаково определять результат каждой проверки.
На Mentoring.digital разберём поиск регрессии по одному граничному случаю. Предполагается, что вы уже умеете читать историю Git и запускать тест проекта.
Допустим, доставка заказа от 5000 рублей должна быть бесплатной. В исправной версии условие написано как total >= 5000, а затем его случайно заменили на total > 5000. Заказ ровно на 5000 обнаруживает ошибку; заказ на 6000 её скрывает. Это учебный пример, а не история реального магазина.
Запустите одну и ту же проверку на старой версии и на текущей. Старый коммит должен проходить её, новый должен падать. Зафиксируйте команду, входные данные, версию интерпретатора и зависимости. Если результат зависит от внешнего API или случайных данных, сначала сделайте сценарий устойчивым.
Не начинайте поиск с предположения «релиз вроде работал». Ошибочная отметка good исключит часть истории, в которой находится дефект.
Bisect переключает содержимое рабочей директории между коммитами. Чтобы не смешивать это с незавершённой работой, создайте дополнительную рабочую директорию из текущего HEAD. Путь ../bisect-lab должен быть новым:
git status
git worktree add --detach ../bisect-lab HEAD
cd ../bisect-lab
git bisect start HEAD v1.0Здесь v1.0 обозначает проверенную исправную версию. Замените её своим существующим тегом или хешем коммита. В новой директории отдельно подготовьте зависимости проекта. Команда git bisect start уже выберет промежуточную ревизию; это нормальное состояние без обычной рабочей ветки.
Выполните проверку в выбранной версии. Если именно исследуемый дефект отсутствует, введите git bisect good. Если он воспроизводится, введите git bisect bad. Повторяйте до сообщения о первом плохом коммите.
git bisect good
# На следующей выбранной версии выполните тест.
# Отметьте good или bad по его результату.
git bisect logНе запускайте good и bad подряд как готовый скрипт: это ответы на разные проверки. Журнал git bisect log помогает понять, какие версии и как были отмечены.
Если старая ревизия не собирается по посторонней причине и тест выполнить нельзя, используйте git bisect skip. Пропуск не означает, что версия исправна. Несколько пропущенных коммитов рядом с границей могут оставить несколько кандидатов.
Для учебного модуля fees.py с функцией delivery_fee сохраните следующий скрипт как check_fee.py рядом с директорией bisect-lab, вне переключаемой истории:
import sys
from pathlib import Path
sys.path.insert(0, str(Path.cwd()))
from fees import delivery_fee
sys.exit(0 if delivery_fee(5000) == 0 else 1)Внутри bisect-lab запустите автоматический поиск. Команда python должна указывать на подготовленный для проекта интерпретатор:
git bisect run python ../check_fee.py
git bisect log
git bisect resetНулевой код завершения означает good. Код 1 в нашем скрипте означает bad. Специальный код 125 предназначен для версии, которую невозможно проверить. Не маскируйте произвольное падение теста этим кодом: можно пропустить нужную границу.
Перед автоматизацией отдельно убедитесь, что команда запуска существует и скрипт импортирует нужный модуль. Коды 126 и 127 Git тоже трактует как плохую версию, хотя оболочка может сообщать ими о проблеме запуска. Падающее окружение способно направить поиск по неверному пути.
Прочитайте изменения найденного коммита через git show. Повторите исходную проверку на нём и на предшествующей исправной версии. На линейной истории это позволяет подтвердить границу. В истории слияний сначала выясните, с каким родителем сравнивать результат.
Команда git bisect reset завершает сеанс и возвращает состояние, с которого он начался. Она не является исправлением ошибки. Найденное изменение может быть корректным само по себе, но выявлять старую проблему в другом месте.
Для этого материала мы создали локальный репозиторий из девяти учебных коммитов, намеренно поменяли условие на шестом и запустили bisect run. Git указал именно этот коммит; после сброса исходный HEAD восстановился. Это проверка сценария на искусственном примере, а не обещание определённой скорости на вашем проекте.
Если проблема проявляется только в CI, полезно разобрать воспроизводимость сборки с ментором по DevOps. А превратить ручной сценарий в устойчивую проверку можно на разборе автотестов с наставником. Для такой встречи подготовьте диапазон коммитов, команду теста и журнал bisect.