Сокращение для просмотра diff предыдущей версии файла

Я могу легко узнать, что изменилось для файла с момента последнего коммита с помощью git diff HEAD^ -- <filename>, но есть ли эквивалентная сокращенная версия для просмотра diff для определенного файла с момента последнего его завершения, независимо от того, сколько из них произошло? Или вернуть N коммитов этого конкретного файла?

Контекст: Я обнаружил ошибку в файле, и я хочу отслеживать ее при загрузке. Достаточно легко получить отчет журнала для определенного файла с git log -<n> <filename>, чтобы показать только которые включали изменения в этот файл. Поэтому я могу просто скопировать и вставить SHA из этого отчета log, но я действительно хочу, чтобы иметь возможность делать что-то вроде git diff ^ -- <filename> или git diff ~2 -- <filename>.

Ответ 1

$ git log -p <filename>

покажет вам сообщение журнала плюс diff для каждой фиксации, которая коснулась именованного файла.

Чтобы показать только отличия от предыдущей версии, попросите только один шаг в истории журнала:

$ git log -1 -p <filename>

Ответ 2

Вы можете использовать форматирование git log, чтобы получить хэши предыдущих коммитов в файл. Например,

git log --pretty=format:'%h' -1 --skip=1 <filename>

вы получите второе от последнего фиксацию, чтобы коснуться определенного файла. На самом деле, если вы не укажете имя файла, это даст вам второе-последнее коммит во всем репозитории. Чтобы получить старые хэши, вы можете настроить псевдоним git, который вызывает функцию оболочки, например:

[alias]
    prior-hash = "!ph() { git log --pretty=format:'%h' -1 --skip=$1 $2; }; ph"

Чтобы использовать его, вы должны ввести что-то вроде git prior-hash n <filename>, где n является (n + 1) -й самой последней версией файла. Таким образом, 1 будет вторым последним фиксацией файла, 2 будет последним, и т.д., А 0 - последним фиксатором для касания этого файла. И снова, имя файла является необязательным, если вы хотите изучить репо в целом.

Я уверен, что вы могли бы выяснить, как построить команду diff отсюда:

[alias]
    prior-hash = "!ph() { git log --pretty=format:'%h' -1 --skip=$1 $2; }; ph"
    diff-prev-easy = "!dp() { git diff $(git prior-hash $1 $2).. $2; }; dp"

который будет использоваться аналогично псевдослучайному хэшу, git diff-prev-easy n <filename>. Это сопоставило бы (n + 1) -ую последнюю ревизию с последней версией файла. Если вы захотите сравнить (n + 1) -ю последнюю ревизию с последней версией n, это простое изменение:

[alias]
    prior-hash = "!ph() { git log --pretty=format:'%h' -1 --skip=$1 $2; }; ph"
    diff-prev = "!dp() { git diff $(git prior-hash $1 $2)..$(git prior-hash $(($1 - 1)) $2) $2; }; dp"

который, опять же, используется таким же образом: git diff-prev n <filename>

Одна из потенциальных проблем, которые следует учитывать, состоит в том, что списки git log фиксируются в хронологическом порядке, что может и не быть тем, что вы хотите. Рассмотрим эту историю:

1 - 2 - - - 4 - 5   master
      \       /
        3 - -       develop

Наша команда git diff-prev 1 создаст разницу между фиксацией 4 и 5, как и ожидалось. Но git diff-prev 2 будет показывать разницу между фиксацией 3 и 4, что, вероятно, нежелательно.

Ответ 3

git blame должен быстро доставить вас в пункт назначения.