Git bisect: как найти коммит, который сломал код

Категория: Git · Язык: Bash · Обновлено:

Команда git bisect ищет коммит, который сломал код, бинарным поиском по истории. Вы называете хороший и плохой коммиты, а git сам предлагает коммиты для проверки. Из 1000 коммитов хватит около десяти проверок.

Ручной поиск

Bash
git bisect start
git bisect bad                  # текущий коммит содержит ошибку
git bisect good v1.0.0          # этот тег или коммит работал верно

Git переключит рабочую папку на коммит примерно в середине диапазона. Проверьте, воспроизводится ли ошибка, и сообщите результат:

Bash
git bisect good                 # на этом коммите ошибки нет
git bisect bad                  # на этом коммите ошибка есть
git bisect skip                 # коммит нельзя проверить, пропустить его

Повторяйте, пока git не напишет «is the first bad commit» и не покажет коммит. Когда поиск закончен, верните ветку на место:

Bash
git bisect reset

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

Если ошибку можно проверить скриптом, поиск проходит без вашего участия. Скрипт должен завершаться с кодом 0 для хорошего коммита и с кодом от 1 до 127 для плохого:

Bash
cat > test.sh <<'EOF'
#!/bin/sh
grep -q "healthy" status.txt
EOF
chmod +x test.sh

git bisect start HEAD v1.0.0
git bisect run ./test.sh
git bisect reset

Код выхода 125 говорит git пропустить текущий коммит: так отмечают коммиты, которые не собираются.

Посмотреть ход поиска

Bash
git bisect log                  # что вы уже отметили
git bisect visualize            # открыть оставшийся диапазон в gitk
git bisect log > bisect.txt     # сохранить журнал
git bisect replay bisect.txt    # повторить его после ошибки в отметках

Использовать другие слова вместо good и bad

Когда ищете не ошибку, а момент изменения поведения, смысл слов меняется:

Bash
git bisect start --term-old=slow --term-new=fast
git bisect fast                 # ускорение появилось здесь

Частые вопросы

Что делать, если я ошибся с отметкой good или bad?

Остановите поиск git bisect reset, а затем повторите его по сохранённому журналу, исправив неверную строку: git bisect replay bisect.txt.

Работает ли bisect с merge-коммитами?

Да, git учитывает всю историю, в том числе слияния. Если вы ищете именно в основной линии, добавьте --first-parent к git bisect start.