Git

В этой статье мы рассмотрим два метода Git для отладки ошибок в базе кода — blame и bisect. С помощью Git blame описываются детали изменения каждой строки в файле, а bisect выполняет бинарный поиск по коммитам. Blame и bisect помогают устранять ошибки в больших базах кода с помощью обнаружения корневого коммита, приводящего к возникновению проблемы.

Подготовка файлов для отладки

Чтобы продемонстрировать функции отладки Git, мы будем использовать репозиторий на GitHub для запуска команд и воспроизведения результатов. Чтобы клонировать репозиторий, выполните следующую команду:

git clone https://github.com/sdaityari/my_git_project/

После завершения процесса клонирования измените активную директорию на клонированную папку.

cd my_git_project
ls -al

Теперь рассмотрим файлы в репозитории.

drwxr-xr-x   9 shaumik  staff   288 Sep 22 17:24 .
drwxr-xr-x+ 40 shaumik  staff  1280 Sep 22 17:24 ..
drwxr-xr-x  12 shaumik  staff   384 Sep 22 17:24 .git
-rw-r--r--   1 shaumik  staff    63 Sep 22 17:24 data.csv
-rw-r--r--   1 shaumik  staff   226 Sep 22 17:24 my_file
-rw-r--r--   1 shaumik  staff    69 Sep 22 17:24 myfile2
-rw-r--r--   1 shaumik  staff    26 Sep 22 17:24 myfile3
-rw-r--r--   1 shaumik  staff   220 Sep 22 17:24 sum.py
-rw-r--r--   1 shaumik  staff   591 Sep 22 17:24 tests.py

Чтобы проверить историю репозитория, выполните команду git log с опцией --oneline.

git log --oneline

Команда git log выводит историю проекта.

c76ee85 (HEAD -> master, origin/master, origin/HEAD) Update data.csv
0d0d493 Added csv data
083e7ee Added yet another test
49a6bec Added more tests
5199b4e ERROR COMMIT: Introduced error in sum.py
b00caea Added tests.py
b117516 Dummy Commit after adding sum.py
7d1b1ec Added sum.py
...
f934591 - Changed two files - This looks like a cooler interfact to write commit messages
8dd76fc My first commit

#5199b4e — это коммит, приводящий к возникновению ошибки в файле sum.py. Файл содержит простую функцию, написанную на Python, которая складывает два числа.

В этом руководстве мы рассмотрим оба метода Git для отладки ошибок в коде. Начнем с Git blame.

Отладка через историю файлов

Зная исходный файл, приводящий к ошибке, можно использовать команду blame, чтобы получить коммит, который внес изменение. Как было сказано выше, ошибка была внесена в файл sum.py, поэтому запускаем команду blame в этом файле.

git blame sum.py

Вывод команды blame выглядит следующим образом:

7d1b1ec5 (Shaumik 2015-05-10 00:43:52 +0530  1) #add_two_numbers.py
7d1b1ec5 (Shaumik 2015-05-10 00:43:52 +0530  2) def add_two_numbers(a, b):
7d1b1ec5 (Shaumik 2015-05-10 00:43:52 +0530  3)     '''
7d1b1ec5 (Shaumik 2015-05-10 00:43:52 +0530  4)         Function to add two numbers
7d1b1ec5 (Shaumik 2015-05-10 00:43:52 +0530  5)     '''
5199b4e1 (Shaumik 2015-05-10 00:50:09 +0530  6)     addition = 0 + b
7d1b1ec5 (Shaumik 2015-05-10 00:43:52 +0530  7)     return addition
7d1b1ec5 (Shaumik 2015-05-10 00:43:52 +0530  8)
7d1b1ec5 (Shaumik 2015-05-10 00:43:52 +0530  9) if __name__ == '__main__':
7d1b1ec5 (Shaumik 2015-05-10 00:43:52 +0530 10)     a = 5
7d1b1ec5 (Shaumik 2015-05-10 00:43:52 +0530 11)     b = 7
7d1b1ec5 (Shaumik 2015-05-10 00:43:52 +0530 12)     print add_two_numbers(a, b)

Команда добавляет к каждой строке файла префикс хэша, автора и времени коммита. Обратите внимание, что ошибка находится в шестой строке файла, в которой к переменной b добавляется ноль вместо переменной a. Команда blame выводит достаточное количество данных, чтобы узнать, что коммит с хэшем #5199b4e1 привнес эту ошибку в код.

Для вывода списка изменений в коммите #5199b4e1 запустите команду git show.

git show 5199b4e1

Команды git show выводит список изменений в коммите.

commit 5199b4e10ba04b63ed1e76118259913123fbf72d
Author: Shaumik <[email protected]>
Date:   Sun May 10 00:50:09 2015 +0530

    ERROR COMMIT: Introduced error in sum.py

diff --git a/sum.py b/sum.py
index 7a3d629..085beee 100644
--- a/sum.py
+++ b/sum.py
@@ -3,7 +3,7 @@ def add_two_numbers(a, b):
     '''
         Function to add two numbers
     '''
-    addition = a + b
+    addition = 0 + b
     return addition

 if __name__ == '__main__':

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

Отладка через бинарный поиск

Команда Git blame используется тогда, когда известен файл, в который было внесено изменение. Представьте сценарий, в котором виден результат ошибки, однако не известно, какая часть кода приводит к ней! В таких случаях на помощь приходит Git bisect.

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

Начнем с мастера bisect.

git bisect start

Затем нужно указать хорошие и плохие коммиты для запуска мастера. Выбираем первый коммит #8dd76fc в истории репозитория в качестве хорошего коммита.

git bisect good 8dd76fc

Поскольку последний коммит содержит ошибку, пометим его как плохой коммит.

git bisect bad c76ee85

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

Bisecting: 9 revisions left to test after this (roughly 3 steps)
[cafb55dde0af6e3ae300c1ba5e68a41fd49f7362] Merge commit '5ef655a4caf8'

Обратите внимание, что у нас есть девять коммитов, следовательно, потребуется примерно три шага (так как 2, возведенное в степень 3, равно 8, что очень близко к 9). При наличии тысячи коммитов потребовалось бы около десяти шагов (так как это процесс бинарного поиска).

На каждом шаге нужно проверять наличие ошибки и передавать либо git bisect good, либо git bisect bad.

$ git bisect good
Bisecting: 4 revisions left to test after this (roughly 2 steps)
[b00caea53381979ec1732d919d6f76e3baaf80fc] Added tests.py
$ git bisect good
Bisecting: 2 revisions left to test after this (roughly 1 step)
[49a6bec7c629e5a84e07c55301f2447f890bad4c] Added more tests
$ git bisect bad
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[5199b4e10ba04b63ed1e76118259913123fbf72d] ERROR COMMIT: Introduced error in sum.py
$ git bisect bad
5199b4e10ba04b63ed1e76118259913123fbf72d is the first bad commit
commit 5199b4e10ba04b63ed1e76118259913123fbf72d
Author: Shaumik <[email protected]>
Date:   Sun May 10 00:50:09 2015 +0530

    ERROR COMMIT: Introduced error in sum.py

:100644 100644 7a3d629df3e91534e7b0cbe082694bee257294d7 085beeea8b099ec16e923ca780d48241906aec8c M	sum.py

Коммит, вызвавший ошибку, успешно определен.

Чтобы выйти из мастера bisect, выполните команду reset.

git bisect reset

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

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

git bisect run [command to run tests]

Если для запуска тестов вы используете команду python tests.py, то замените вторую команду на следующую:

git bisect run python tests.py

Заключение

В этом руководстве мы рассмотрели простой пример для объяснения двух динамических и полезных инструментов Git. Таким образом, если вы знаете исходный файл ошибки, то используйте команду Git blame, а если известно лишь поведение ошибки, то вам нужен процесс bisect.

Читайте также:


Перевод статьи Shaumik Daityar: Debugging with Git