Как сделать git diff игнорировать комментарии

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

Меня не интересуют измененные комментарии, поэтому я хотел бы иметь git diff игнорировать все строки, соответствующие ^\s*\*.*$, так как это все комментарии (часть/* */).

Я не могу найти способ сообщить git diff игнорировать определенные строки.

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

Есть ли способ сделать это?

Ответы

Ответ 1

git diff -G <regex>

И укажите регулярное выражение, которое НЕ соответствует вашей номерной строке версии.

Ответ 2

Вот решение, которое хорошо работает для меня. Я написал решение и дополнительную дополнительную документацию по опции git (log|diff) -G<regex>.

В основном, используя те же решения, что и выше, но специально для комментариев, начинающихся с * или #, а иногда и пробела перед *... Но по-прежнему необходимо разрешить #ifdef, #include и т.д.

Посмотрите вперед и посмотрите, по-видимому, не поддерживается опцией -G, а вообще-то ?, и у меня были проблемы с использованием *. +, похоже, работает хорошо.

(обратите внимание, проверено на Git v2.7.0)

Версия для нескольких строк комментариев

git diff -w -G'(^[^\*# ])|(^#\w)|(^\s+[^\*#])'
  • -w игнорировать пробелы
  • -G отображаются только строки разностей, соответствующие следующему регулярному выражению
  • (^[^\*# /]) любая строка, которая не начинается со звезды или хэша или пробела
  • (^#\w) любая строка, начинающаяся с #, за которой следует буква
  • (^\s+[^\*#/]) любая строка, начинающаяся с некоторого пробела, за которым следует символ комментария

В принципе, привязка svn изменяет каждый файл и выходит прямо сейчас и изменяет многострочные блоки комментариев в каждом файле. Теперь я могу отличить мои изменения от svn без информации fyi, что svn падает в комментариях.

Технически это позволит отображать комментарии на python и bash, такие как #TODO в diff, и если оператор разделения запущен в новой строке в С++, его можно было бы игнорировать:

a = b
    / c;

Также документация на -G в Git показалась довольно недостаточной, поэтому информация здесь должна помочь:

git diff -G<regex>

-G<regex>

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

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

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

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

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

(обратите внимание, проверено на Git v2.7.0)

  • -G использует основное регулярное выражение.
  • Нет поддержки синтаксиса regex ?, *, !, {, } {, }.
  • Группировка с группами () и OR-ing работает с |.
  • Поддерживаются символы Wild Card, такие как \s, \W и т.д.
  • Поддержка поиска и поиска не.
  • Начальные и конечные привязки строк ^$ работают.
  • Функция доступна с Git 1.7.4.

Исключенные файлы v Исключенные разницы

Обратите внимание, что параметр -G фильтрует файлы, которые будут различаться.

Но если файл "разнятся", те строки, которые были "исключены/включены" раньше, будут показаны в diff.

Примеры

Показывать только разницу файлов по крайней мере с одной строкой, в которой упоминается foo.

git diff -G'foo'

Показать разницу в файлах для всех, кроме строк, начинающихся с #

git diff -G'^[^#]'

Показать файлы с разницами, обозначающими FIXME или TODO

git diff -G`(FIXME)|(TODO)`

См. также git log -G, git grep, git log -S, --pickaxe-regex, --pickaxe-all

UPDATE: какое средство regex используется в опции -G?

https://github.com/git/git/search?utf8=%E2%9C%93&q=regcomp&type=

https://github.com/git/git/blob/master/diffcore-pickaxe.c

if (opts & (DIFF_PICKAXE_REGEX | DIFF_PICKAXE_KIND_G)) {
    int cflags = REG_EXTENDED | REG_NEWLINE;
    if (DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE))
        cflags |= REG_ICASE;
    regcomp_or_die(&regex, needle, cflags);
    regexp = &regex;

// and in the regcom_or_die function
regcomp(regex, needle, cflags);

http://man7.org/linux/man-pages/man3/regexec.3.html

   REG_EXTENDED
          Use POSIX Extended Regular Expression syntax when interpreting
          regex.  If not set, POSIX Basic Regular Expression syntax is
          used.

//...

   REG_NEWLINE
          Match-any-character operators don't match a newline.

          A nonmatching list ([^...])  not containing a newline does not
          match a newline.

          Match-beginning-of-line operator (^) matches the empty string
          immediately after a newline, regardless of whether eflags, the
          execution flags of regexec(), contains REG_NOTBOL.

          Match-end-of-line operator ($) matches the empty string
          immediately before a newline, regardless of whether eflags
          contains REG_NOTEOL.

Надеюсь, что это поможет.

Ответ 3

Мне было проще использовать git difftool для запуска внешнего diff:

git difftool -y -x "diff -I '<regex>'"

Ответ 4

Найден решение. Я могу использовать эту команду:

git diff --numstat --minimal <commit> <commit> | sed '/^[1-]\s\+[1-]\s\+.*/d'

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

Ответ 5

Возможно, bash script как это (я не тестировал код, дайте мне знать, можете ли вы заставить его работать или нет)

#!/bin/bash
git diff --name-only "[email protected]" | while read FPATH ; do
    LINES_COUNT=`git diff --textconv "$FPATH" "[email protected]" | sed '/^[1-]\s\+[1-]\s\+.*/d' | wc -l`
    if [ $LINES_COUNT -gt 0 ] ; then
        echo -e "$LINES_COUNT\t$FPATH"
    fi
done | sort -n

Ответ 6

Использование 'grep' для вывода git diff:

git diff -w | grep -c -E "(^[+-]\s*(\/)?\*)|(^[+-]\s*\/\/)"

Только изменения в комментариях могут быть рассчитаны. (А)

Использование вывода git diff --stat ':

git diff -w --stat

могут быть рассчитаны все изменения строк. (В)

Чтобы получить счетчик изменений строки исходного кода (NCSL), вычитайте (A) из (B).

Объяснение: На выходе git diff (в котором игнорируются пробелы),

  • Посмотрите на строку, начинающуюся с "+" или "-", что означает модифицировано линия.
  • После этого могут быть дополнительные символы пробела. '\ s *'
  • Затем найдите шаблон строки комментария '/*' (или) только '*' (или) '//'.
  • Так как опция '-c' задана с помощью grep, просто распечатайте счетчик. Удалите параметр "-c", чтобы увидеть комментарии только в разностях.

ПРИМЕЧАНИЕ. В подсчете строк комментариев могут возникать незначительные ошибки из-за следующих допущений, и результат должен приниматься как показатель шара.

  • 1.) Исходные файлы основаны на языке C. Файлы Makefile, Shell script имеют разные условные обозначения '#' для обозначения строк комментария и, если они являются частью diffset, строки комментариев не будут считаться.

  • 2.) GIT соглашение о смене строки: если строка изменена, GIT видит, что эта конкретная строка удаляется, и там добавляется новая строка, и она может выглядеть как две строки изменены тогда как в действительности одна строка модифицируется.

    В приведенном ниже примере новое определение "FOO" выглядит как изменение строки.

    $GIT diff --stat -w abc.h
    ...
    - # define FOO 7
    + # определить FOO 105
    ...
    1 файл изменен, 1 вставка (+), 1 удаление (-)
    $

  • 3.) Допустимые строки комментариев, не соответствующие шаблону (или) Допустимые строки исходного кода, соответствующие шаблону, могут вызывать ошибки в вычислении.

    В приведенном ниже примере строка "+ blah blah", которая не начинается с "*", не будет отображаться как строка комментария.

           + /*   
           +  blah blah  
           + *   
           + */
    

    В приведенном ниже примере строка "+ * ptr" будет считана как строка комментария, так как она начинается с *, хотя это допустимая строка исходного кода.

            + printf("\n %p",  
            +         *ptr);