Jak grepować różnice git?


81

Czy istnieje sposób pokazania git-diff przefiltrowanego przez dany wzorzec.

Coś jak

git grepdiff pattern

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

Niestety najprostsze rozwiązanie nie wystarczy

git diff | grep pattern 

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

Przyszedłem z obejściem przy użyciu awk

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

Ale chciałbym się dowiedzieć, że jest na to polecenie.


3
Najwyraźniej projekt github o nazwie git-diff-grep robi coś zupełnie innego.
Kuba

Odpowiedzi:


99

Nie git diff -G <regex>jesteś pewien, ale czy flaga nie jest OK?

-G <wyrażenie regularne>

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

15
nie jest to dokładnie to, czego szukam, ponieważ chcę zobaczyć tylko linie pasujące do wzorca, a nie całą różnicę plików, które zawierają zmianę ze wzorcem
Kuba

to chyba nie ma prostszego rozwiązania niż twoje
CharlesB

Przynajmniej git diff -G jest lepszym pierwszym krokiem niż pełny różnic git.
Kuba

1
Moja wersja nie ma flagi -G. Czy został usunięty?
RedX

3
Przydatne także do sprawdzenia, których plików dotyczy wyrażenie regularne:git diff -G <regex> --raw
Raman


11

Inną możliwością byłoby obejrzenie całego pliku diff i wyszukanie wyniku przy użyciu zwykłych lesspoleceń (wpisz, /a następnie wzorzec).

Jeśli lessskonfigurowałeś wyświetlanie niektórych linii przed użyciem dopasowania --jump-target=N, jest to całkiem przydatne. Spróbuj tak:

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

Oznacza to, że dopasowanie powinno być pokazane w linii 10 (pokazuje 9 linii kontekstu powyżej), co może wystarczyć, aby zobaczyć również nazwę pliku.

Możesz też użyć np. --jump-target=.5Aby ustawić mecz na środku ekranu.


3

Używam git log -p, który otwiera się mniej (choć konfigurowalny), którego z kolei można wyszukiwać za pomocą /. Jest też git log -S <searchword>.


Znam je - nie patrzę w historię, ale w aktualne zmiany robocze.
Kuba

W porządku, w takim razie można użyć tej samej metody (zacytowanej przez Robinst). Jeśli chcesz uzyskać wynik, prawdopodobnie możesz użyć dowolnej biblioteki używającej libgit2 lub gitgui / gitk.
chelmertz

1

To wykonało pracę za mnie, mam nadzieję, że komuś pomoże:

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

1

Myślę, że twoje podejście do diffwyjścia „grep” jest najlepszym obejściem.

Możesz ulepszyć swój skrypt awk, używając seda:

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: regex, aby dopasować kolorowe linie terminala
  • marker: znacznik odpowiadający podziałowi z różnych diffporcji, linie zaczynające się od kolorowego „diff”
  • pattern: wzorzec do wyszukania, linie zaczynające się od kolorowego „+” lub „-” i zawierające „WZORZEC”

Spowoduje to wydrukowanie porcji pełnego różnicowania, z dodanym lub usuniętym WZOREM, zachowując również przydatne kolorowe wyjście.

Zauważ, że ^[in coloredpowinno być rzeczywiste, dosłowne ^[. Możesz wpisać je w bash, naciskając Ctrl+ V, Ctrl+[


świetny!! dla każdego, kto próbuje to wpisać w innym miejscu niż powłoka bash (np. edytując plik .sh w IDE), musisz zamienić coś ^[podobnego, colored=$'(\e\[[0-9;]*[a-zA-Z])'a na macOS również musisz brew install gnu-sedi wymienićsed --> gsed
Anentropic

0

Oto niestandardowe narzędzie porównywania, które umożliwia grepowanie zmian (ale nie kontekstu):

Stosowanie

GIT_EXTERNAL_DIFF="mydiff --grep foo" git diff

Spowoduje to wyświetlenie tych wierszy w zmianach, które zawierają foo (w tym wiersze, w których foozniknęły z powodu wprowadzonych zmian). Zamiast niego można użyć dowolnego wzorca grep foo.

Każdy wiersz wyjściowy zaczyna się od następującego przedrostka:

filename: oldlinenum: newlinenum|

Skryptu można również używać bez rozszerzenia --grep opcji, w którym to przypadku po prostu formatuje pełny plik różnicowy (tj. Zapewnia pełny kontekst), jak opisano powyżej.

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

W systemie Windows proste rozwiązanie to:

git diff -U0 | findstr string

Jeśli chcesz grupować według nazwy pliku, użyj tego

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

0

Korzystam z tego z wielką satysfakcją :)

grep -ri <MY_PATTERN> $(git diff 790e26393d --name-only) 
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.