использование git для сравнения одного файла из двух коммитов

#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