#git #debugging #git-diff
#git #отладка #git-diff
Вопрос:
У меня есть файл, который сломался где-то в конце строки, и я нашел последнюю точку, в которой это все еще было исправлено.
Я хотел бы знать, как, используя git, я могу сравнить один файл из двух коммитов, или действительно ли это лучший способ воспроизвести это!!
Ответ №1:
Чтобы напрямую ответить на ваш вопрос, предположим, вы хотите сравнить файл src/toaster.c
между вашим текущим master
и старым коммитом f4l4f3l
, вы можете просто сделать:
git diff master f4l4f3l -- src/toaster.c
В качестве альтернативы вы можете просто просмотреть все изменения в этом файле с помощью:
git log -p -- src/toaster.c
В более общем плане, однако, если вы пытаетесь найти коммит, в котором была допущена конкретная ошибка, у git есть замечательный инструмент для этого, который называется git bisect. Если вы укажете этому инструменту рабочий и нерабочий коммиты, он выдаст вам серию коммитов для тестирования между ними, используя стратегию бинарного поиска.
Вы бы начали разделять пополам с помощью команды:
git bisect start
Затем, если ваш текущий коммит содержит ошибку, вы просто делаете:
git bisect bad
Далее вам нужно найти более старый коммит, в котором определенно не было ошибки. У этого может быть определенный тег, или, возможно, вы просто выберете коммит, который был несколько месяцев назад. Предположим, что вызван один из них a12b3d
, тогда вы должны сделать:
git checkout a12b3d
git bisect good
На этом этапе git обработает следующий коммит, который вам нужно будет протестировать, и сделает git checkout
, чтобы переместить вас к этому коммиту. (Все эти извлечения будут с «отсоединенным заголовком», поэтому ваш исходный указатель ветви не изменился.) Затем вы тестируете этот коммит и запускаете git bisect good
или git bisect bad
в зависимости от того, есть в нем ошибка или нет. Этот бинарный поиск между ревизиями быстро сузит круг до первого неудачного коммита и сообщит, какой это. Затем, чтобы вернуться к тому, что вы делали, вы можете сделать:
git bisect reset
Комментарии:
1. Спасибо за это, но прежде чем я начну, не следует ли мне использовать ‘bisect good’ после нахождения коммита, в котором нет ошибки?
2. Упс, да — так и должно было быть
git checkout a12b3d; git bisect good
. Теперь я исправил эту опечатку в ответе.3. Хорошо, итак, я нашел свой неудачный коммит, и я могу видеть, что не так. Каков наилучший способ сейчас изменить это и перенести его вперед?
4. Хорошо, итак, я просмотрел последний удачный коммит, увидел проблему, перешел к первому неудачному коммиту и исправил его, затем я выделил этот коммит в требуемой ветке. Оглядываясь назад, я мог бы с таким же успехом просто переключиться на текущую версию и исправить ее напрямую.
5. @Mild Fuzz: да, как только вы определили ошибку, самый простой способ ее исправить — просто зафиксировать исправление в конце вашей ветки. Однако тогда у вас есть множество вариантов — например, если в плохом коммите нет ничего хорошего, вы могли бы просто использовать
git revert
; если вы не сделали эту историю общедоступной, вы могли бы исправить этот коммит во время интерактивной перебазировки; и т.д. и т.п.
Ответ №2:
git diff $start_commit..$end_commit -- path/to/file
Например, вы видите разницу для файла file.c
между текущим моментом и двумя предыдущими коммит
git diff HEAD^^..HEAD -- file.c