Git diff показує лише змінені рядки


128

Коли я роблю git diff, він показує додані рядки:

+ this line is added

рядки, які були видалені:

- this line is removed

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

this line is not modified
this line is also not modified

Це призводить до того, що фактично git різняться приблизно так:

+ this line is added
  this line is not modified
- this line is removed
  this line is not modified

Чи можу я попросити git показувати лише рядки, які були змінені, і ігнорувати всі інші коди, які не були змінені? Я написав метод, який видалить усі рядки, у яких перед ними знак "+" або "-", але я впевнений, що для цього повинен бути більш простий спосіб.

В моєму git diff, мені цікаво лише побачити зміни, які були змінені.

Заздалегідь спасибі.

Відповіді:


182

Те, що ви хочете, - це різниця з 0 рядками контексту. Ви можете створити це за допомогою:

git diff --unified=0

або

git diff -U0

Ви також можете встановити це як параметр config для цього сховища:

git config diff.context 0

Щоб встановити його глобально, для будь-якого сховища:

 git config --global diff.context 0

4
Дякую за швидку відповідь. Це вирішує половину моєї проблеми, але я все ще отримую такі рядки, як "@@ -1 +1 @@" в моєму розрізі, а верхній мій git diff має "diff --git a / db / xxxxxxx b / db / xxxx index xxxxx..aaaaaaa bbbbbbbb
r3b00t

3
Я не думаю, що git не забезпечує жодного способу уникнути виведення цих рядків, тому що diff не матиме сенсу без них (ви не могли б знати, який файл ви шукали, ні де ви знаходились у файлі).
Кріс Хейс

8
@Rakesh: Щоб розширити, git-diff спроби створити diff, які насправді можуть бути використані як патчі до вихідних файлів, що без цієї інформації неможливо. Єдиний спосіб її видалити - це самообробку, наприклад, через via git diff | egrep "^(\+|-) ".
Кріс Хейс

1
git config --global diff.context 0 щоб встановити його в усьому світі
Анджей Реманн

Якщо ви хочете побачити в конкретному каталозі, спробуйте git diff -U0 <dir>
Eswar Yaganti

41

Інший хак (на ип * х) , щоб показати тільки рядки , що починаються з +і -:

git diff -U0 | grep '^[+-]' | grep -Ev '^(--- a/|\+\+\+ b/)'

Код, наведений вище, робить наступне:

  • git diff -U0: виберіть 0 контекстних рядків
  • Перший греп включає лише всі рядки, що починаються з +або-
  • Другий греп виключає лінії, що починаються з --- a/або+++ b/

Колір

Щоб показати кольорову різницю, спробуйте наступне:

git diff -U0 --color | grep '^\e\[[^m]*m[-+]' | grep -Ev '(--- a/|\+\+\+ b/)'
  • Вираз, ^\e\[[^m]*m[-+]шукає початок рядка ( ^), потім функцію адміністрування ( \e), за [якою разом розпочинають послідовність втечі, потім будь-який символ, який не є "м" (цифри, крапки з комою чи нічого), а потім " м ", що закінчує послідовність втечі.
  • Зауважте, що всі наведені нижче дії є дійсними послідовностями: \e[0m(скинути), \e[m(також скинути), \e[1m(жирним шрифтом), \e[31m(червоний), \e[32m(зелений), \e[9;31m(закреслити + червоний), \e[31;9m(червоний + закреслити), \e[1;4;9;31m(жирний + підкреслити + закреслити + червоне). За замовчуванням кольори git використовують червоний та зелений, але їх можна переналаштувати.
  • --colorте саме, що --color=always.
  • Обмеження на --- a/або +++ b/відображатись на початку рядка було знято для розміщення послідовностей евакуації, і це може призвести до крайового випадку.

Додаткові нотатки:

  • Вище рішення повинно бути змінено , якщо використовувати додаткові опції мерзотник Diff , такі як -R, --src-prefix, --dst-prefix, --no-prefixі т.д.
  • Два грепи можуть бути об'єднані в єдину grep -E -v '^(\+\+\+ b/|--- a/|@@ |diff --git|index )', але мені здається, що версія подвійного грепу легше зрозуміти.

2
Хороший. Оновіть чітке пояснення щодо кожного фільтра.
henrebotha

Я бачу багато git diffрядків типу "заголовка", які починаються з @@, але які git diffрядки починаються з ---або +++? Я не знав цих.
Габріель Степлес

Ах, ніколи. Вони позначають імена файлів для файлів, які містять доповнення ( +++) або видалення ( ---). Я зараз це бачу: git-scm.com/docs/git-diff#_combined_diff_format .
Габріель Степлес

Повторне виправлення: --- a/filenameначебто позначає "файл зліва" або файл, як це було раніше, і, +++ b/filenameсхоже, позначає "файл праворуч", або файл, як зараз, зі своїми змінами. Я настільки звик використовувати git difftoolз meld , що показує прекрасні побічні порівняння, що я ніколи насправді не звик дивитись git diff, тому мені це все одно дивно, і я ніколи не переглядав ці нюанси раніше.
Габріель Степлес

1
@GabrielStaples, додана підтримка кольору. Дякую.
користувач650654

6

Слідкуючи за останнім коментарем Кріса, головна проблема з післяобробкою полягає в тому, що ви хочете продовжувати рядки, починаючи з, -|+але ви також хочете відфільтрувати ті, з яких починається ---|+++. Якщо ви зберігаєте патч-файли у вашій репо- репортажі (у мене в Pydoop ), з іншого боку, ви хочете зберегти рядки, які починаються з цього --|++, тож регулярний вираз буде задіяний:

git diff | grep -P '^\+(?:(?!\+\+))|^-(?:(?!--))'

У регулярному вираженні використовується негативний підхід: детальне пояснення див. У відповіді Пітера Баутона на це запитання .

Якщо ви робите це часто, ви можете налаштувати псевдонім git для нього:

git config --global alias.diffonly '!git diff | grep -P "^\+(?:(?!\+\+))|^-(?:(?!--))"'

1
це не спрацювало для мене на Windows git bash. Не знаю, чому (греп сказав недійсний варіант Р), не майте чуттпа шукати це в даний момент.
Денніс

1
-Pабо --perl-regexpвикористовується для інтерпретації шаблону як регулярної репресії Perl, але не завжди реалізується. Мені це не спрацювало на OSX. gnu.org/software/grep/manual/grep.html#grep-Programs
Willington Vega

5

Я думаю, що для простих випадків регулярний вираз може бути набагато коротшим і простіше запам’ятати, з застереженням, що це не працюватиме, якщо у вас є зміни рядка там, де сама лінія починається з +або-

$ git diff | grep '^[+|-][^+|-]'

У регулярному вираженні зазначено, що рядок повинен починатися з +або -, і безпосередньо наступний символ не повинен бути жодним із цих. Я отримав ті ж результати, чи врятувався я +тут, чи ні, btw ...


Приклад:

$ cat testfile
A
B
C
D
E
F
G

Скажіть, я переходжу Cна X, EнаY і Gна Z.

$ git diff | grep '^[+|-][^+|-]'
-C
+X
-E
+Y
-G
+Z

Як я вже говорив вище, хоча це для більшості випадків. Якщо ви передаєте цей вихід у файл dout, спробуйте той же регулярний вираз, він не працюватиме.

$ git diff dout | grep '^[+|-][^+|-]'
$

У будь-якому випадку, сподівайтеся, що допоможе у вашому випадку


У випадках, коли рядок починається з "-", він не працюватиме. Приклад: - name: No pdbу файлі yaml.
anapaulagomes

3

Ця відповідь збереже початкові червоні / зелені кольори для читабельності. Я надав кілька варіантів синтаксису:

git diff --color | grep --color=never $'^\e\[3[12]m'
git diff --color | grep --color=never $'^\033\[3[12]m'
git diff --color | grep --color=never -P '^\e\[3[12]m'
git diff --color | grep --color=never -P '^\033\[3[12]m'

Пояснення:

  • The git diff --colorНеобхідно для запобігання ублюдка від відключення кольору , коли він трубопровід.
  • The grep --color=neverЄ запобігання Grep видалення оригінального кольору і виділяючи знайдену рядок.
  • Ми підбираємо рядки, які починаються червоним ( \e[31m) або зеленим (\e[32m ) кодів втечі.
  • $'...'(ANSI-C , з посиланням на синтаксис) або -P(Perl синтаксис) повинен дозволити , grepщоб інтерпретувати \eабо в \033якості ESCсимволу.

Дякую за це Ось альтернативна форма, яку я щойно придумав. Ваша $''частина особливо мені допомогла. stackoverflow.com/a/61929887/4561887
Габріель Степлес

1

Як використовувати awkдля показу лише рядки +та -рядки, що враховують будь-яке кольорове або форматування тексту, git diffможе виводитись:

Ні один з інших відповідей тут (включаючи мою іншу відповідь ) не зробить точно те, що ви хочете на 100% правильно. Однак ця відповідь буде. Ось 1-лайнер, який можна скопіювати та вставити у свій термінал. Я щойно зробив це кілька рядків для читабельності - ви можете скопіювати і вставити його однаково в будь-якому випадку, щоб я міг зробити його читабельним! Він спирається на awkмову програмування:

git diff --color=always "$@" | awk '
# 1. Match and then skip "--- a/" and "+++ b/" lines
/^(\033\[(([0-9]{1,2};?){1,10})m)?(--- a\/|\+\+\+ b\/)/ {
    next 
} 
# 2. Now print the remaining "+" and "-" lines ONLY! Note: doing step 1 above first was required or
# else those lines would have been matched by this matcher below too since they also begin with 
# the "+" and "-" symbols.
/^(\033\[(([0-9]{1,2};?){1,10})m)?[-+]/ {
    print $0 
}
' | less -RFX

Ось його особливості. Усі ці особливості, якщо взяти їх разом, вирішують недоліки кожної іншої відповіді тут:

  1. Він обробляє кольоровий І кольоровий вихід. Ось що робить цей регулярний вираз:^(\033\[(([0-9]{1,2};?){1,10})m)?
  2. Він обробляє ВСІ КОЛЬОРИ І ВСІ ТЕКСТИ, КОТОРІ ФОРМУВАННЯ ТЕКСТУ, включаючи жирний шрифт, курсив, закреслення тощо, які ви можете встановити у своїх git configналаштуваннях . Саме тому регулярний вираз вище , має ;?і {1,10}в ній: якщо він виявляє початок кольору або текстове форматування коди, він буде відповідати до 10 послідовностей цих комбінованих кодів ANSI.
  3. Він також не включає рядки, які починаються з @@слова і словаdiff , як це робиться у прийнятій відповіді . Якщо ви хочете, щоб ті рядки (які, чесно кажучи, я вважаю корисними :)), зробіть це замість цього:

    git diff --unified=0
    

    або

    git diff -U0
    
  4. Він показує вихід таким же чином, як git diffі: в lessпейджері з необов'язковим кольоровим виведенням ( -R), і лише якщо текст> 1 сторінка (-F ), і при збереженні поточної сторінки тексту на екрані при quit ( -X) .

Це також має перевагу бути потужним і легко налаштовуватися, оскільки він використовує мову програмування awk.

Якщо ви зацікавлені в навчанні awk , ось деякі ресурси:

  1. gawk (ГНУ awkПосібник ): https://www.gnu.org/software/gawk/manual/html_node/index.html#SEC_Contents
  2. Вивчення git diffn та коментарі до них: https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles/blob/master/useful_scripts/git-diffn.sh
    1. Якщо ви git diffnтеж хочете , що git diffвідповідає номерам рядків, дивіться тут: Git diff з номерами рядків (Git log з номерами рядків)
  3. Деякі приклади тесту "привіт світу" та синтаксису: https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/tree/master/awk

Як бонус я також завершив вищезазначене, щоб використовуватись як git diffc, що означає "git diff для показу ТІЛЬКИ" змін ". Використання є ідентичним з git diff; просто використовуйте git diffcзамість цього! Він підтримує ВСІ опції. Колір за замовчуванням увімкнено. Щоб вимкнути його, просто використовуйте git diffc --no-colorабоgit diffc --color=never . Детальніше man git diffдив.

Оскільки я щойно закінчив git diffn (інструмент для показу git diffрядком 'n'umber) минулої ночі, написання git diffcбуло тривіальним. Я подумав, що мені краще це робити зараз, поки знання в моїй голові свіжі.

Встановити git diffc :

Дотримуйтесь інструкцій в кінці цієї відповіді тут , крім випадків, де ви бачите git-diffnінструкції, використовуйте git-diffcнатомість. Це включає і в wgetкоманду. Завантажити та встановити досить git diffcпросто: це лише кілька команд.


0

Ось ще один, простіший спосіб знайти лише змінені лінії, а отже, починати з одного +або -, зберігаючи кольоровий вихід:

git diff -U0 --color=always HEAD~ | grep --color=never -E $'^\e\[(32m\+|31m-)'
  1. -U0Каже включити 0 рядків контексту навколо змінених ліній - тобто включати тільки змінені рядки самі. Див man git diff.
  2. -EДля Grep дозволяє йому працювати з розширеними регулярними виразами
  3. $''Синтаксис , по- видимому дозволяє ANSI квотування, який правильно інтерпретує ESC (втеча, або 0x1B) символів правильно. Дивіться тут .
  4. А ось опис регексу від https://www.regex101.com :введіть тут опис зображення
  5. В основному, ^відповідає початку рядка, \eвідповідає знаку Escape, який є початком кольорового коду в терміналі, \[відповідає наступному знаку в кольоровому коді, який є [, а потім (this|that)синтаксис відповідає "цьому" або "тому" , де "це" 32m+, що являє собою зелений + рядок, і31m- є червоною - лінією.
  6. Кольори такі: \e[32mзелений і \e[31mчервоний.
  7. +показує рядки, позначені git diffяк додані, звичайно, і -рядки, позначені git diffяк видалені.
  8. Зауважте, що --color=neverце потрібно у другому grepвиразі для того, щоб він не виділяв його збіги, які в іншому випадку накручували б кольорові коди, що надходять git diffзліва.
  9. Також +слід уникати символу, \+оскільки в іншому випадку +це особливий регулярний вираз (регулярний вираз), який вказує одне або кілька входів попереднього елемента . Дивіться тут: https://en.wikipedia.org/wiki/Regular_expression#Basic_concepts .

Список літератури:

  1. https://git-scm.com/docs/git-diff#_combined_diff_format
  2. Відповідь від @ user650654: Git diff відображає лише змінені рядки
  3. Відповідь @wisbucky: Git diff показує лише змінені рядки

Пов'язані:

  1. [моя власна відповідь] Git diff з номерами рядків (Git журнал з номерами рядків)
  2. [чужа відповідь] Git відрізняється від номерів рядків (журнал Git з номерами рядків)
  3. git отличается від номерів рядків та правильного вирівнювання / відступу коду
  4. git-filechange-search.sh- скрипт, який дозволяє шукати у файлі ім’я змінної чи функції та з'ясувати, які коміти містять зміни із цією назвою змінної чи функції. Вих. використання: ./git-filechange-search.sh path/to/my/file.cpp variable_nameзнайде всі коміти зі змінами file.cpp, які містяться variable_nameв них. Це корисно, щоб побачити, де і коли були змінені певні функції. Це як би пошук, який міг би спостерігати розділи файлу, що відображаються git blameпротягом часу.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.