Git bisect. Ищем баги с помощью гита
Сколько раз такое было? Начинаешь делать новую задачу, создаешь ветку от мастера, сидишь, коммитишь себе и вдруг - бац! Вылезает бага. Причем из старого функционала, то, что раньше точно работало.
Начинаешь разбираться, откуда эта бага взялась. Для начала переключаешься на мастер, проверяешь - там работает. Ага, значит, это сам в своей ветке накосячил. Надо искать у себя. Каким образом - есть разные варианты.
Если ты хорошо знаешь модуль, где всплыла бага, то возможно, достаточно будет немного посидеть и подумать. Сузить круг поиска, найти куски кода, где вероятнее всего, бага и закралась. Способ работает, но реже, чем хотелось бы.
Другой вариант, засесть и последовательно анализировать цепочку вызовов функций, отслеживать переменные в отладчике, разбираться во взаимосвязях отдельных частей системы. Способ тоже неплохой, но очень трудозатратный.
Думаешь дальше. Так, у нас же гит, коммиты и все такое. Коммиты для того и придуманы, чтобы писать код итеративно. Раз есть коммиты, значит, в какой-то из них и влезла бага - хорошо бы этот коммит найти.
Вроде нет проблем, переключаться между коммитами можно. git checkout hash_commit и все. Переключился на предыдущий коммит, проверил. Если баги нет, значит, косяк в последнем коммите, начинаешь искать там. А если бага осталась, значит, проблема еще раньше - переключаешься на коммит раньше, снова проверяешь. И так пока не найдешь проблемный коммит.
Вроде звучит все просто. Но проблема в том, что это годится, если в ветке 3 коммита, их и перебрать можно. А если 10? А если 50 или 100? Ну, например, ветка долгоживущая. Что теперь, по очереди всю сотню перебирать? А если бага в самом начале случилась? Двигаться с конца?
Тут вспоминаем, что мы вообще-то программисты и алгоритмы умеем. А еще вспоминаем игру, которой можно сильно удивить любого первоклассника. Мол, давай ты загадаешь число от 1 до 100, а я буду пытаться угадать. Я называю число, а ты говоришь, твое задуманное больше или меньше. И спорим, что за 7 попыток угадаю? За 7, а не за 100! Чудеса.
Конечно, мы понимаем простой принцип этой игры и знаем, как называть числа, каждый раз сужая варианты ровно в 2 раза. Было бы неплохо использовать эту магию и при поиске багов. Но только неохота руками вылавливать коммиты и прыгать по истории гита взад и вперед. На наше счастье все это уже сделано до нас.
git bisect работает ровно по такому принципу бинарного поиска. Сначала мы задаем круг поиска - указываем коммит, когда все работало хорошо. А дальше git bisect переключится на коммит по центру этого диапазона и будет ждать от нас ответа, есть ли на этом коммите бага или нет. Если бага есть, то bisect отсечет "верхнюю" половину и прыгнет на середину "нижнего" диапазона. Если баги нет, то наоборот. Все, как и в игре с угадайкой в числа. git bisect будет спрашивать нас до тех пор, пока не останется один единственный коммит, тот самый, бажный.
Давайте посмотрим на примере, как это работает.
Я взял наш проект интернет-магазина, создал новую ветку и накомитил туда 8 коммитов. Вот так это выглядит в PhpStorm
Коммиты сделаны от балды, но пронумерованы от 1 до 8. Это сделал, чтобы было удобнее смотреть, как git bisect делает свои переключения. Будем следить шаг за шагом.
В один из этих коммитов я внес злую багу, но в какой именно - не скажу. Мы проведем расследование с помощью git bisect и найдем зловреда. Если интересно, бага заключается в том, что при клике "Добавить в корзину" товар не добавляется, а выскакивает alert('Error'). Да, на такие "баги" натравливать bisect смешно, тут простой ctrl+F спасет, но мы же понимаем, что реальные баги не такие простые.
Начинаем искать. Открываем консоль и вбиваем туда git bisect start. Это первое, мы говорим, мол, bisect, давай начинай.
Дальше второе, пишем git bisect bad - это означает, что текущий коммит у нас "плохой", с багой. И третье - нужно указать "хороший коммит", тот, где баги еще не было.
У меня это будет коммит №1 с хэшем f6f2339...
Команда git bisect good f6f2339ba01331a7d7ec7e1324616101fe516199
Как мы и ожидаем, git bisect переключает нас на середину - на коммит №4
Проверяем добавление товара в браузере, ага, бага осталась. Пишем в консоли, git bisect bad. То есть больше никаких хэшей не упоминаем, только говорим, плохой коммит или хороший. Дальше git bisect разберется за нас. Вот что происходит в консоли
Нас кинули на третий коммит. Чтобы убедиться, смотрим в PhpStorm
Проверяем - опять есть бага. Снова пишем git bisect bad и нас переключают на коммит №2
Проверяем - баги нет. Пишем теперь git bisect good и опа! Ну вы, наверно, уже догадались :)
is the first bad commit. Автор, дата и message коммита - весь расклад. Зловред найден, это коммит №3. Хочется посмотреть, что же в нем такого написано. Но сейчас мы находимся на коммите №2, поэтому третий даже не видим в PhpStorm. Да и с git bisect мы закончили, нужно завершить его работу и вернуться в нормальное состояние. Пишем git bisect reset и возвращаемся в начало, к коммиту №8.
Давайте же посмотрим на этот третий коммит. Откроем git diff в PhpStorm и видим волшебный код
Да, я в функцию клика по кнопке "Добавить" просто написал alert('Error') и return false. Не делайте так :-)
Все, осталось убрать эти строчки и баг пофикшен.
Конечно, многое зависит от того, какой у вас будет искомый коммит. Если там изменений на 500 строк в 30 файлах, то искать сам баг будет непросто. Но все равно легче, когда знаем, что косяк именно в этом коммите. Кстати, это еще один аргумент в пользу того, чтобы делать коммиты как можно меньше. Маленькие коммиты легче читать и проще отлаживать. Но в любом случае, знание конкретного коммита облегчит поиск и исправление проблемы.
Вот и все. Такой он, git bisect, страшно звучит, но просто работает.
Всем поменьше багов и любите гит :-)
Все статьи о git
- Курс "Git для начинающих". Видеоуроки
- Git merge vs rebase для начинающих
- Git fork. Что такое форки и как с ними работать
- Как я перестал бояться и полюбил git
- Git bisect. Ищем баги с помощью гита
- 12 причин работать с гитом в командной строке
- Как склеить коммиты в git
- Мой набор команд при работе с git
- Как работать с git в Modx
- Как установить git в Linux Mint
- Визуализация истории git с помощью Gource
Истории из жизни айти и обсуждение кода.