Статьи

Отладка в Git с помощью Blame и Bisect

Когда вы работаете с огромной кодовой базой, вы можете обнаружить ошибки в вашем коде (или, что еще хуже, в чужом коде), которые мешают вам продолжать работу в процессе разработки. Вы можете проверить старый коммит, чтобы увидеть, была ли там ошибка — но часто это худший способ сделать это. Представьте, что у вас есть сотня коммитов, чтобы проверить — сколько времени будет потрачено впустую?

К счастью, в Git есть два инструмента, которые помогут вам в отладке. Мы посмотрим на оба и попытаемся понять их варианты использования. Давайте начнем с намеренного внесения ошибки в наш код:

Преднамеренное добавление строки ошибки

Я добавил в файл my_file которая является нежелательной и предположительно вызывает ошибку. Я также добавляю несколько коммитов после этого, чтобы похоронить ошибочный коммит. Давайте проверим, что ошибочная строка была добавлена ​​в файл, выполнив следующее:

 cat my_file 

Неисправный файл

Обратите внимание на «Нежелательную линию», которая предположительно вызывает ошибку.

Отладка с обвинением

Как только вы обнаружили ошибку, вы можете знать или не знать местонахождение неисправного кода. Допустим, что вы делаете. В нашем случае, скажем, вы знаете, что my_file вызывает проблемы. В этом случае мы можем запустить следующую команду, чтобы получить больше информации о строках в файлах и о коммитах, которым принадлежат эти строки.

 git blame my_file 

обвинять содержимое файла

Если вы посмотрите на вывод команды git blame , вы увидите, что коммит 0bf63b53 — это то, что 0bf63b53 к ошибке («нежелательная строка»). Если вы хотите проверить, что еще было изменено в этом коммите, или хотите получить больше информации о том же самом, вы можете выполнить следующее:

 git show 0bf63b53 

работает мерзавец на плохом коммите

Вот и все — теперь мы знаем, какой коммит вызвал ошибку, а что еще было изменено в этом коммите. Мы можем приступить к исправлению ошибки.

Отладка с помощью Bisect

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

Я упомяну это еще раз — git bisect для такой тривиальной ситуации, как наше дело, излишне. Однако я прохожу этот процесс только для демонстрационных целей.

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

Для начала нам нужно выбрать «хороший» коммит, в котором ошибки нет. Затем нам нужно выбрать «плохой» коммит, где присутствовала ошибка (в идеале, последний коммит, содержащий ошибку, чтобы вы могли назначить его как «плохой»). Затем Git проведет вас по последним коммитам и спросит, являются ли они «хорошими» или «плохими», пока не найдет виновника. По сути, это алгоритм бинарного поиска по массиву коммитов, чтобы найти, какой коммит был первым «плохим» коммитом.

Здесь очень важно отметить, что в этом процессе вы должны искать одну ошибку. Если у вас есть несколько ошибок, вам нужно выполнить бинарный поиск для каждой из ошибок.

Работая с той же ошибкой в ​​случае с git blame , мы предполагаем, что не знаем, в каком файле произошла ошибка. Чтобы проверить, присутствует ли ошибка в определенном cat my_file , мы запустим cat my_file чтобы увидеть, cat my_file ли содержимое файла нежелательную строку.

Запустите мастер git bisect

Мы запустим следующую команду, чтобы сообщить Git, что мы находимся в бинарном режиме поиска, чтобы найти ошибку:

 git bisect start 

Выберите хороший коммит

После запуска мастера нам нужно сообщить Git о коммите, где все работало. Давайте рассмотрим историю коммитов, чтобы найти коммит, который мы хотим.

 git log --oneline 

История проекта

Мы используем 8dd76fc , который является самым старым:

 git bisect good 8dd76fc 

Выберите неверный коммит

После того, как мы присвоили «хороший» тэг для хорошего коммита, нам нужно найти плохой коммит, чтобы Git мог искать между этими двумя и сообщать нам, где была введена ошибка. Поскольку мы знаем, что в последнем 1094272 ( 1094272 ) есть ошибка, мы пойдем с ней:

 git bisect bad 1094272 

Назначить коммиты как «Хорошие» или «Плохие»

Как только мы назначили наши хорошие и плохие коммиты (которые служат начальным и конечным указателями для нашего поиска), Git проводит нас по коммитам и спрашивает, содержит ли каждый коммит ошибку.

Запуск мастера git bisect

Обратите внимание на скриншот, что 7 ревизий будут покрыты примерно за 3 шага. Количество шагов растет логарифмически . Поскольку 2 2 <7 <2 3 , нам нужно три шага. Если бы было сто ревизий, нам понадобилось бы примерно 7 шагов, а если бы была тысяча ревизий, нам понадобилось бы около 10 шагов.

Теперь нам представлен commit cc48fb и нам нужно выяснить, хороший это или плохой коммит. В нашем случае мы проверяем содержимое файла и видим, присутствует ли нежелательная строка:

Проверка содержимого my_file

Поскольку строки нет, мы обозначаем ее как хороший коммит.

 git bisect good 

Мы продолжаем этот процесс в течение следующих нескольких шагов, пока git bisect найдет первый неверный коммит:

мерзавец находит плохой коммит

После того, как мы закончили с коммитом, нам нужно выйти из режима бинарного поиска Git:

 git bisect reset 

Git bisect reset - возвращение в старое состояние

Возможно, вы захотите взглянуть на эту прекрасную заставку Git Bisect, которая проведет вас через процесс, который я обсуждал.

Автоматизация процесса

Мы прошли интерактивный процесс отладки в Git. Если вы знакомы с модульным тестированием, вы можете написать модульный тест, который идентифицирует ошибку. Если вы хотите запускать тесты автоматически, вам нужно предоставить Git сценарий теста, который вы написали.

 git bisect start git bisect run [location_to_script_file] 

Замените location_to_script_file фактическим местоположением файла скрипта, удалив квадратные скобки.

Вот учебник о том, как механизировать процесс отладки в Git в PHP .

Вывод

Мы взяли слишком упрощенный случай, чтобы объяснить очень мощную концепцию. Если вы знаете, в каком файле содержится неверный код, вам следует подумать об этом, не задумываясь. Однако, если вы не знаете, что является причиной ошибки, и ваш репозиторий достаточно большой, с огромной историей, git bisect определенно git bisect .

Как вы отлаживаете свой код? Вам нравится бинарный поиск в Git? У вас есть лучший способ сделать то же самое? Дайте нам знать в комментариях ниже.