В этой статье мы рассмотрим два метода Git для отладки ошибок в базе кода — blame и bisect. С помощью Git blame описываются детали изменения каждой строки в файле, а bisect выполняет бинарный поиск по коммитам. Blame и bisect помогают устранять ошибки в больших базах кода с помощью обнаружения корневого коммита, приводящего к возникновению проблемы.
Чтобы продемонстрировать функции отладки Git, мы будем использовать репозиторий на GitHub для запуска команд и воспроизведения результатов. Чтобы клонировать репозиторий, выполните следующую команду:
git clone https://github.com/sdaityari/my_git_project/После завершения процесса клонирования измените активную директорию на клонированную папку.
cd my_git_projectls -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
выводит историю проекта.
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 в этом файле.
Вывод команды 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
выводит список изменений в коммите.
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 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 run [command to run tests]Если для запуска тестов вы используете команду python tests.py
, то замените вторую команду на следующую:
В этом руководстве мы рассмотрели простой пример для объяснения двух динамических и полезных инструментов Git. Таким образом, если вы знаете исходный файл ошибки, то используйте команду Git blame, а если известно лишь поведение ошибки, то вам нужен процесс bisect.
Перевод статьи Shaumik Daityar: Debugging with Git
Комментарии