Як зігріти git diff?


81

Чи є спосіб показати git-diff, відфільтрований за заданим шаблоном.

Щось на зразок

git grepdiff pattern

changed file
+++ some sentence with pattern
changed file 2
--- some other pattern

На жаль, найпростіше рішення недостатньо хороше

git diff | grep pattern 

+++ some sentence with pattern
--- some other pattern
# not an option as doesn't put the filename close to the match

Я прийшов із обхідним шляхом, використовуючи awk

git diff | awk "/\+\+\+/{f = \$2}; /PATTERN/ {print f \$0} "

Але я хотів би дізнатися, що для цього існує команда.


3
Очевидно, проект github під назвою git-diff-grep робить щось зовсім інше.
Куба

Відповіді:


99

Не впевнені, але чи не git diff -G <regex>позначено прапор?

-G <регулярний вираз>

Look for differences whose added or removed line matches the given <regex>.

15
це не зовсім те, що я шукаю, оскільки я хочу бачити лише рядки, які відповідають шаблону - не всю різницю файлів, що включають зміни із шаблоном
Куба

то, мабуть, немає більш простого рішення, як у вас
CharlesB

Принаймні, git diff -G - перший перший крок, ніж повний git diff.
Куба

1
У моїй версії немає прапора -G. Це було видалено?
RedX

3
Також корисно побачити, на які файли впливає регулярний вираз:git diff -G <regex> --raw
Раман


11

Іншою можливістю було б переглянути всю різницю та здійснити пошук вихідних даних, використовуючи звичайні lessкоманди (тип, /а потім шаблон).

Коли ви lessналаштували показувати рядки перед матчем --jump-target=N, це дуже корисно. Спробуйте так:

PAGER="/usr/bin/less --jump-target=10" git diff

Це означає, що збіг повинен відображатися в рядку 10 (показано 9 рядків контексту вище), чого може бути достатньо, щоб також побачити назву файлу.

Ви також можете використовувати, наприклад, --jump-target=.5щоб змусити розташувати сірник посередині екрана.


3

Я використовую git log -p, що відкриває менше (щоправда, конфігурується), який, у свою чергу, можна шукати /. Є також git log -S <searchword>.


Я з ними знайомий - я дивлюся не на історію, а на поточні робочі зміни.
Куба

Гаразд, тоді міг бути використаний той самий метод (як цитується Робінст). Якщо вам потрібні результати, ви можете скористатися будь-якою бібліотекою за допомогою libgit2 або gitgui / gitk.
chelmertz

1

Це зробило роботу для мене, сподіваюся, це комусь допоможе:

git diff | grep  -P '^\+|^\-'

1

Я думаю, що ваш підхід до "grep" diffрезультатів є найкращим обхідним шляхом.

Ви можете вдосконалити свій сценарій awk, використовуючи sed:

colored="(^[\[[0-9;]*[a-zA-Z])"
marker="^$colored+diff"
pattern="^$colored+.*(\+|\-).*PATTERN"
git diff --color | sed -rn -e "/$marker/! H; /$marker/ ba; $ ba; b; :a; x; /$pattern/ p"
  • colored: регулярний вираз для відповідності кольоровим лініям терміналу
  • marker: маркер, що відповідає поділу з різних diffкусків, лінії, що починаються з кольорової " різниці "
  • pattern: шаблон для пошуку, рядки, що починаються з кольорового "+" або "-" і містять "ШАБЛОН"

Це дозволить надрукувати повні різниці, з доданим або видаленим ШАБЛОНОМ, а також збереження корисного кольорового виводу.

Зверніть увагу, що ^[in coloredмає бути фактичним, буквальним ^[. Ви можете ввести їх у bash, натискаючи Ctrl+ V, Ctrl+[


відмінно !! для тих, хто намагається ввести це десь, крім оболонки bash (наприклад, редагування файлу .sh в IDE), вам потрібно замінити ^[подібне, colored=$'(\e\[[0-9;]*[a-zA-Z])'а на macOS - це також потрібно brew install gnu-sedта замінитиsed --> gsed
Anentropic

0

Ось спеціальний інструмент diff, який дозволяє захоплювати зміни всередині (але не контекст):

Використання

GIT_EXTERNAL_DIFF="mydiff --grep foo" git diff

Це видасть ті рядки у ваших змінах, які містять foo(включаючи рядки, які fooзникли через ваші зміни). Замість, можна використовувати будь-який шаблон grep foo.

Кожен вихідний рядок починається з наступного префікса:

filename: oldlinenum: newlinenum|

Сценарій також може використовуватися без --grepопції, і в цьому випадку він просто форматує повну різницю (тобто забезпечує повний контекст), як описано вище.

mydiff

#!/bin/bash

my_diff()
{
    diff --old-line-format="$1"':%6dn:      |-%L'     \
         --new-line-format="$1"':      :%6dn|+%L'     \
         --unchanged-line-format="$1"':%6dn:%6dn| %L' \
         $2 $3
}

if [[ $1 == '--grep' ]]
then
    pattern="$2"
    shift 2
    my_diff "$1" "$2" "$5"|grep --color=never '^[^|]\+|[-+].\+'"$pattern"'.*'
else
    my_diff "$1" "$2" "$5"
fi

exit 0

0

У Windows просте рішення:

git diff -U0 | findstr string

Якщо ви хочете згрупувати за назвою файлу, використовуйте це

FOR /F "usebackq delims==" %i IN (`git diff --name-only`) do git diff -U0 %~fi | findstr string

0

Я використовую це з великим задоволенням :)

grep -ri <MY_PATTERN> $(git diff 790e26393d --name-only) 
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.