игнорирование изменений, соответствующих строке в git diff

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

Все изменения имеют вид

-                       "main()",
+                       OOMPH_CURRENT_FUNCTION,

где main () может быть именем любой функции. Я хочу создать различие всех изменений, не относящихся к этой форме.

Параметры -G и -S для git diff поразительно близки - они находят изменения, которые ДОЛЖНЫ соответствовать строке или регулярному выражению.

Есть хороший способ сделать это?

Попытки пока

Другой вопрос описывает, как можно отрицать регулярные выражения, используя этот подход я думаю, что команда должна быть

git diff -G '^((?!OOMPH_CURRENT_FUNCTION).)*$'

но это просто возвращает сообщение об ошибке

fatal: invalid log-grep regex: Invalid preceding regular expression

поэтому я думаю, что git не поддерживает эту функцию регулярного выражения.

Я также заметил, что стандартный unix diff имеет параметр -I, чтобы «игнорировать изменения, все строки которых соответствуют RE». Но я не могу найти правильный способ заменить собственный diff git на инструмент unix diff.


person dshepherd    schedule 08.04.2013    source источник
comment
Если вы можете найти все совпадающие изменения, сохраните их в файле и git diff | fgrep -vxf file   -  person tripleee    schedule 08.04.2013
comment
Возможно, вы также могли бы сохранить результат git diff в файле и использовать лучший инструмент регулярных выражений.   -  person Loamhoof    schedule 08.04.2013
comment
@tripleee Это сработало, спасибо! Это не идеальное решение, но если вы его перепишете как ответ, я его приму.   -  person dshepherd    schedule 08.04.2013
comment
@Loamhoof Я подумал об этом, но я думаю, что вам нужно будет правильно проанализировать вывод diff, чтобы иметь возможность удалять все изменения (а не просто удалять отдельные строки).   -  person dshepherd    schedule 08.04.2013
comment
Если это повторяющаяся проблема, стоит попробовать настроить драйвер фильтра .gitattribute для изменений (stackoverflow.com/a/ 12969603/520162). При этом файлы даже не будут отображаться как измененные, если main() заменяется на OOMPH_CURRENT_FUNCTION.   -  person eckes    schedule 08.04.2013
comment
@tripleee На самом деле, подумав еще над проблемой, я не думаю, что ваше решение безопасно. В приведенном выше примере, если произошло другое изменение, включающее строку «- main ()», оно было бы скрыто в diff (в то время как остальная часть изменения все еще была бы там). Это могло сбивать с толку!   -  person dshepherd    schedule 09.04.2013
comment
Это полностью оправдывает запрос функции ...   -  person naught101    schedule 21.07.2017


Ответы (4)


Попробуйте следующее:

$ git diff > full_diff.txt
$ git diff -G "your pattern" > matching_diff.txt

Затем вы можете сравнить их так:

$ diff matching_diff.txt full_diff.txt

Если все изменения соответствуют шаблону, full_diff.txt и matching_diff.txt будут идентичны, и последняя команда diff ничего не вернет.

Если есть изменения, не соответствующие шаблону, последний diff выделит их.


Вы можете объединить все вышеперечисленные шаги и избежать создания двух дополнительных файлов, например:

diff <(git diff -G "your pattern") <(git diff)  # works with other diff tools too
person Elmar Peise    schedule 09.04.2013
comment
Это работает, и я не вижу никаких очевидных проблем (кроме странного форматирования вывода), поэтому я принимаю это. Спасибо! Я все еще думаю, что должен быть способ сделать это лучше. - person dshepherd; 10.04.2013
comment
Умная. Это именно то решение, которое мне нравится с моим набором инструментов (vim). Было бы даже лучше, если бы git-diff выросла отрицательная -G опция, чтобы имитировать, как -x работает GNU diff ... :) - person sehe; 02.07.2016
comment
-G соответствует всему файлу, а не только измененному разделу. Это означает, что любые другие изменения в файлах, которые также включают ваше нежелательное изменение, будут проигнорированы. - person Xorax; 03.02.2020

Используйте git difftool, чтобы запустить настоящий diff.

Пример: https://github.com/cben/kubernetes-discovery-samples/commit/b1e946434e73d8d1650c887f7d49b46dcbd835a6
Я создал сценарий, работающий diff так, как я хочу (здесь я сохраняю curl --verbose выходных данных в репозитории, что приводит к скучным изменениям каждый раз, когда я повторно запускаю завиток):

#!/bin/bash
diff --recursive --unified=1 --color \
     --ignore-matching-lines=serverAddress \
     --ignore-matching-lines='^\*  subject:' \
     --ignore-matching-lines='^\*  start date:' \
     --ignore-matching-lines='^\*  expire date:' \
     --ignore-matching-lines='^\*  issuer:' \
     --ignore-matching-lines='^< Date:' \
     --ignore-matching-lines='^< Content-Length:' \
     --ignore-matching-lines='--:--:--' \
     --ignore-matching-lines='{ \[[0-9]* bytes data\]' \
     "$@"

И теперь я могу запустить git difftool --dir-diff --extcmd=path/to/above/script.sh и увидеть только интересные изменения.

Важное предостережение относительно GNU diff -I aka --ignore-matching-lines: это просто предотвращает превращение таких строк в кусок "интересного", но когда эти изменения появляются в одном фрагменте с другими неотмеченными изменениями, он все равно будет их отображать. Я использовал --unified=1 выше, чтобы уменьшить этот эффект, сделав куски меньше (только 1 строка контекста выше и ниже каждого изменения).

person Beni Cherniavsky-Paskin    schedule 08.07.2018

Grep больше не нужен!

В Git 2.30 (первый квартал 2021 г.) (kempniu).
(Объединено Junio ​​C Hamano - gitster - в commit 1ae0949, 2 ноября 2020 г.)

diff: добавьте -I<regex>, который игнорирует соответствующие изменения

Подписано: Michał Kępień

Добавьте новый параметр сравнения, который позволяет игнорировать изменения, все строки которых (измененные, удаленные и добавленные) соответствуют заданному регулярному выражению.
Это похоже на параметр _7 _ / _ 8_ в автономных diff утилит и может использоваться, например, игнорировать изменения, которые влияют только на комментарии к коду, или искать несвязанные изменения в коммитах, содержащих большое количество автоматически применяемых модификаций (например, замену строки по всему дереву).

Разница между _10 _ / _ 11_ и новой опцией -I заключается в том, что последний фильтрует вывод для каждого изменения.

Используйте поле «игнорировать» в xdchange_t, чтобы пометить изменение как проигнорированное или нет.
Так как это же поле используется --ignore-blank-lines, для --ignore-blank-lines и -I применяются одинаковые правила выдачи фрагментов.
Эти два параметра также могут быть используются вместе в одном git вызове (они дополняют друг друга).

Переименуйте xdl_mark_ignorable() в xdl_mark_ignorable_lines(), чтобы указать, что он логически является родственником xdl_mark_ignorable_regex(), а не его родительским элементом.

diff-options теперь включает в свою r Arnf Bjarmason (avar).
(Объединено Junio ​​C Hamano - gitster - < / a> в commit 45df6c4, 22 февраля 2021 г.

diff: устраните утечку памяти из regcomp () на {log,diff} -I

Подписал: var Arnfjör Bjarmason

Исправьте утечку памяти в 296d4a9 (diff: add -I, который игнорирует соответствующие изменения, 2020 г. -10-20, Git v2.30.0-rc0 - объединить, перечисленные в пакет № 3), освободив память, которую он выделяет во вновь введенном diff_free().

Эта утечка памяти была намеренно введена в 296d4a9, см. обсуждение его предыдущей итерации.

В то время освобождение памяти было несколько утомительным занятием, но, поскольку с новым diff_free() этого больше нет, давайте воспользуемся этим.

Давайте сохраним шаблон для diff_free_file() и добавим diff_free_ignore_regex(), хотя (в отличие от "diff_free_file") нам не нужно вызывать его где-то еще.
Я думаю, это сделает код более читабельным, чем постепенное накопление гигантской diff_free() функции, разделяющей int i по несвязанный код и т. д.

person VonC    schedule 09.11.2020
comment
Требование соответствия всех строк делает это несколько неудобным. Вы можете минимизировать вероятность того, что все строки столкнутся с другими изменениями, настроив количество контекстных строк (например, --unified=1, как упоминалось by Beni), но нельзя выкидывать неинтересные изменения, если они граничат с интересными. - person Michael; 25.01.2021
comment
@Michael Хорошее замечание. Я все еще думаю, что это интересное дополнение к git diff, каким бы неудобным оно ни было. - person VonC; 25.01.2021

Думаю, у меня есть другое решение, использующее трубы и grep. У меня было два файла, которые нужно было проверить на различия, которые не включали @@ и g:, поэтому я сделал это (заимствовал из здесь и здесь и здесь:

$ git diff -U0 --color-words --no-index file1.tex file2.tex | grep -v -e "@@" -e "g:"

и это, похоже, помогло. Цвета все еще были там.

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

person kcrisman    schedule 29.06.2019