Показать все коммиты, diff которых содержат определенную строку

Как говорится в названии, я хочу найти каждое сообщение, чей diff содержит определенную строку.

В настоящий момент я использую

git log -p 'filename'

который показывает менее похожий интерфейс каждого diff, где я ищу строку. Затем я возвращаюсь, чтобы найти фактическое сообщение об ошибке.

Простая альтернатива может заключаться в том, чтобы pipe git log -p в grep, но я не могу найти идентификатор или сообщение commit таким образом.

Ответы

Ответ 1

Здесь однострочная оболочка script (разбита на несколько строк для целей форматирования), которая извлекает оборотные номера коммитов текущей-ветки, влияющих на path, где git show -p содержит заданный pattern, Он не идеален (он будет соответствовать сообщениям фиксации, а также различиям), но это должно быть легко настроить, как вам нравится, отсюда.

git rev-list HEAD -- path |
while read rev; do
    if git show -p $rev | grep pattern >/dev/null; then
        echo $rev
    fi
done

Обратите внимание, что вы можете заменить git show на, например, git diff $rev^ $rev (обратите внимание, что это только сравнивается с первичным родителем, если это слияние) или git whatchanged $rev, или что угодно. Основной трюк состоит в том, чтобы начать с git rev-list, чтобы извлечь все кандидаты (фиксации влияют на данный путь; опустите часть -- path, чтобы получить все фиксации, начиная с HEAD). См. git -rev-list (1) для многих других вещей, которые вы можете сделать с помощью git rev-list.

Ответ 2

git log -p -S'string'

может использоваться для поиска коммитов, которые добавляют или удаляют строку. Он не ведет себя точно так же, потому что он соответствует только коммитам, которые фактически добавляют или удаляют экземпляр шаблона, а не (например) коммитам, где это происходит в контексте diff. Но, может быть, это достаточно хорошо для вас.

Ответ 3

Я знаю, что на этот вопрос был дан ответ на некоторое время, но я тоже натолкнулся на это, и нашел другое решение, поэтому решил, что поделюсь. Git-log -G-переключатель должен делать то, что вы делаете, где -S-переключатель будет выводить только то, что число вхождений совпадающего изменения строки.

Из Git-log man-страница:

-G     Ищите различия, текст патча которых содержит добавленные/удаленные строки, которые соответствуют.

Чтобы проиллюстрировать разницу между -S --pickaxe-regex и -G, рассмотрите фиксацию со следующим diff в том же файле:

+    return !regexec(regexp, two->ptr, 1, &regmatch, 0);
...
-    hit = !regexec(regexp, mf2.ptr, 1, &regmatch, 0);

В то время как git log -G "regexec (regexp" покажет это commit, git log -S "regexec (regexp" --pickaxe-regex не будет (поскольку количество вхождений этой строки не изменилось).

Для получения дополнительной информации см. запись кирка в gitdiffcore (7).

Ответ 4

git log --all -G'my_search' -i -m -p

мнемоника: git log all GIMP

  • --all: поиск по всем возможным путям, а не только через HEAD.
  • -G: более общий, чем -S потому что -S ищет только различия, которые показывают разное количество вхождений my_search. -G ищет полные различия и принимает регулярные выражения.
  • -i [опционально]: заставить -G игнорировать регистр.
  • -m: по умолчанию git log не выводит diff для коммитов слияния. -m изменяет это поведение по умолчанию, делая слияние фиксирует вывод полных различий. Это очень важно: если неправильно сформированный коммит слияния изменил вашу строку, вы не сможете увидеть без -m.
  • -p: также выводить полный патч для каждого найденного коммита.

Вы даже можете подключить это к VIM. Я нахожу это очень полезным:

git log --no-color --all -G'regex' -i -m -p | vim -

здесь я использую --no-color потому что vim выделяет для меня патчи.

Ответ 5

Если вы используете linux, проведите его через egrep и выполните поиск в регулярном выражении

git log -p 'filename' | egrep '(yourstring|commit-message)'

Ответ 6

Считаете ли вы использование команды pipe и grep?

Пример:

 git log -p | grep 'filename'

Ответ 7

Вы можете использовать git для этого, например:

git log --grep="filename"

Или в определенном файле:

git log --grep="filename" README