Git diff, aby pokazać tylko linie, które zostały zmodyfikowane

128

Kiedy robię różnicę git, pokazuje linie, które zostały dodane:

+ this line is added

linie, które zostały usunięte:

- this line is removed

ale pokazuje również wiele wierszy, które nie są modyfikowane:

this line is not modified
this line is also not modified

Powoduje to, że rzeczywisty różnic git wygląda mniej więcej tak:

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

Czy mogę poprosić git o pokazanie tylko zmodyfikowanych wierszy i zignorowanie pozostałego kodu, który nie został zmodyfikowany? Napisałem metodę, która usunie wszystkie linie, które nie mają przed sobą znaku „+” lub „-”, ale jestem pewien, że musi istnieć prostszy sposób, aby to zrobić.

W moim git diff interesuje mnie tylko wyświetlanie zmodyfikowanych linii.

Z góry dziękuję.

r3b00t
źródło

Odpowiedzi:

182

To, czego chcesz, to różnica z 0 liniami kontekstu. Możesz to wygenerować za pomocą:

git diff --unified=0

lub

git diff -U0

Możesz również ustawić to jako opcję konfiguracji dla tego repozytorium:

git config diff.context 0

Aby ustawić to globalnie, dla dowolnego repozytorium:

 git config --global diff.context 0
Chris Hayes
źródło
4
Dziękuję za szybką odpowiedź. To rozwiązuje połowę mojego problemu, ale nadal pojawiają się linie takie jak „@@ -1 +1 @@” w moim pliku różnicowym, a na górze mojego pliku różnicowego widnieją „diff --git a / db / xxxxxxx b / db / xxxx index xxxxx..aaaaaaa bbbbbbbb
r3b00t
3
Nie sądzę, aby git w jakikolwiek sposób pozwolił uniknąć wypisywania tych linii, ponieważ różnica bez nich nie miałaby sensu (nie można było wiedzieć, który plik oglądasz ani gdzie się znajdujesz).
Chris Hayes,
8
@Rakesh: Aby rozwinąć, git-diff próbuje utworzyć różnice, które mogą być faktycznie używane jako łaty do plików źródłowych, co jest niemożliwe bez tych informacji. Jedynym sposobem na usunięcie tego byłoby samodzielne przetworzenie, na przykład przez git diff | egrep "^(\+|-) ".
Chris Hayes,
1
git config --global diff.context 0 mieć to ustawione globalnie
Andrzej Rehmann
Jeśli chcesz zobaczyć w określonym katalogu, spróbuj git diff -U0 <dir>
Eswar Yaganti
41

Kolejny hack (na un * x), aby pokazać tylko linie zaczynające się od +i -:

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

Powyższy kod wykonuje następujące czynności:

  • git diff -U0: wybierz 0 linii kontekstu
  • Pierwszy grep zawiera tylko wszystkie wiersze zaczynające się od +lub-
  • Drugi grep wyklucza wiersze zaczynające się od --- a/lub+++ b/

Kolor

Aby wyświetlić kolorowe różnice, spróbuj wykonać następujące czynności:

git diff -U0 --color | grep '^\e\[[^m]*m[-+]' | grep -Ev '(--- a/|\+\+\+ b/)'
  • Wyrażenie ,, ^\e\[[^m]*m[-+]szuka początku wiersza ( ^), następnie znaku ucieczki ( \e), po [którym następuje razem początek sekwencji sterującej , a następnie dowolnego znaku innego niż „m” (liczby, średniki lub nic), po którym następuje „ m ”, co kończy sekwencję ucieczki.
  • Zauważ, że wszystkie poniższe są prawidłowymi sekwencjami ucieczki: \e[0m(reset), \e[m(także reset), \e[1m(pogrubienie), \e[31m(czerwony), \e[32m(zielony), \e[9;31m(przekreślenie + czerwony), \e[31;9m(czerwony + przekreślenie), \e[1;4;9;31m(pogrubienie + podkreśl + przekreśl + czerwony). Domyślne kolory git to czerwony i zielony, ale można je zmienić.
  • --colorjest taki sam jak --color=always.
  • Ograniczenie dotyczące --- a/lub +++ b/pojawiania się na początku linii zostało usunięte, aby uwzględnić sekwencje ucieczki, co może prowadzić do skrajnego przypadku.

Dodatkowe uwagi:

  • Powyższe rozwiązanie musi zostać zmodyfikowany, jeśli użyć dodatkowych opcji git diff, takie jak -R, --src-prefix, --dst-prefix,--no-prefix , itd
  • Dwa elementy grep można połączyć w jeden grep -E -v '^(\+\+\+ b/|--- a/|@@ |diff --git|index )', ale wydaje mi się, że wersja podwójnego grepa jest łatwiejsza do zrozumienia.
user650654
źródło
2
Niezłe. Głosuj za jasnym wyjaśnieniem każdego filtra.
henrebotha
Widzę wiele git difflinii typu „nagłówek”, które zaczynają się od @@, ale co to są git difflinie zaczynające się od ---lub +++? Nie byłem tego świadomy.
Gabriel Staples
Ah nie ważne. Oznaczają one nazwy plików, które zawierają dodatki ( +++) lub usunięcia ( ---). Widzę to teraz tutaj: git-scm.com/docs/git-diff#_combined_diff_format .
Gabriel Staples
Korekta jeszcze raz: --- a/filenamewydaje się oznaczać „plik po lewej stronie” lub plik taki, jaki był wcześniej, i +++ b/filenamewydaje się oznaczać „plik po prawej stronie”, lub plik taki, jaki jest teraz z twoimi zmianami. Jestem tak przyzwyczajony do używania git difftoolz meldowaniem , które pokazuje piękne porównania obok siebie, do których nigdy się nie przyzwyczaiłem git diff, więc nadal wygląda to dla mnie dziwnie i nigdy wcześniej nie patrzyłem na te niuanse.
Gabriel Staples
1
@GabrielStaples, dodano obsługę koloru. Dzięki.
user650654
6

Nawiązując do ostatniego komentarza Chrisa, głównym problemem związanym z przetwarzaniem końcowym jest to, że chcesz zachować wiersze zaczynające się od, -|+ale chcesz też odfiltrować te, które zaczynają się od ---|+++. Z drugiej strony, jeśli przechowujesz pliki łatek w swoim repozytorium (robię to w Pydoop ), chcesz zachować linie zaczynające się od --|++, więc wyrażenie regularne staje się nieco zaangażowane:

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

Wyrażenie regularne używa ujemnego wyprzedzenia: zobacz odpowiedź Petera Boughton na to pytanie, aby uzyskać szczegółowe wyjaśnienie.

Jeśli robisz to często, możesz chcieć skonfigurować dla niego alias git:

git config --global alias.diffonly '!git diff | grep -P "^\+(?:(?!\+\+))|^-(?:(?!--))"'
simleo
źródło
1
to nie działa dla mnie na Windows git bash. Nie wiem dlaczego (grep powiedział, że opcja P jest nieprawidłowa), nie mam teraz tyle bezczelności, żeby się temu przyjrzeć.
Dennis
1
-Plub --perl-regexpjest używany do interpretowania wzorca jako regularnej ponownej ekspresji Perla, ale nie zawsze jest implementowany. Nie działało na mnie na OSX. gnu.org/software/grep/manual/grep.html#grep-Programs
Willington Vega
5

Myślę, że w prostych przypadkach wyrażenie regularne może być znacznie krótsze i łatwiejsze do zapamiętania, z zastrzeżeniem, że nie zadziała, jeśli masz zmiany wiersza, w których sama linia zaczyna się od +lub-

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

Wyrażenie regularne mówi, że wiersz powinien zaczynać się od + lub -, a następujący po nim znak nie powinien być żadnym z tych znaków. Mam takie same wyniki, czy uciekłem +tutaj, czy nie, przy okazji ...


Przykład:

$ cat testfile
A
B
C
D
E
F
G

Powiedz, że zmieniam się Cna X, Ena Yi Gna Z.

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

Jak powiedziałem powyżej, dotyczy to jednak tylko większości przypadków. Jeśli potokujesz to wyjście do pliku dout, a następnie wypróbuj to samo wyrażenie regularne, to nie zadziała.

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

Tak czy inaczej, mam nadzieję, że to pomoże w twoim przypadku

galois
źródło
W przypadkach, w których linia zaczyna się od „-”, nie będzie działać. Przykład: - name: No pdbw pliku yaml.
anapaulagomes
3

Ta odpowiedź zachowa oryginalne czerwono-zielone kolory dla czytelności. Podałem kilka odmian składni:

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'

Wyjaśnienie:

  • Jest git diff --colorto potrzebne, aby uniemożliwić gitowi wyłączenie koloru podczas przesyłania rur.
  • Ma grep --color=neverto zapobiec usunięciu przez grep oryginalnego koloru i podświetleniu dopasowanego ciągu.
  • Dopasowujemy wiersze zaczynające się od czerwonych ( \e[31m) lub zielonych ( \e[32m) kodów ucieczki.
  • $'...'(ANSI-C składnia cytowanie) lub -P(Perl składni) to niech grepinterpretować \ealbo \033jako ESCpostać.
wisbucky
źródło
Dzięki za to. Oto alternatywny formularz, który właśnie wymyśliłem. Twoja $''rola szczególnie mi pomogła. stackoverflow.com/a/61929887/4561887
Gabriel Staples
1

Jak używać, awkaby wyświetlać tylko linie +i -, uwzględniając dowolny kolor lub formatowanie tekstu git diff:

Żadna z pozostałych odpowiedzi tutaj (w tym moja druga odpowiedź ) nie zrobi dokładnie tego, co chcesz w 100% poprawnie. Ta odpowiedź jednak będzie. Oto 1-liniowiec, który możesz skopiować i wkleić do swojego terminala. Właśnie utworzyłem go w wielu wierszach, aby był czytelny - możesz go skopiować i wkleić w ten sam sposób w obie strony, więc równie dobrze mogę uczynić go czytelnym! Opiera się na awkjęzyku programowania:

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

Oto jego cechy. Wszystkie te cechy razem wzięte rozwiązują wady każdej innej odpowiedzi tutaj:

  1. Obsługuje wydruki kolorowe ORAZ bez koloru. To właśnie robi to wyrażenie regularne:^(\033\[(([0-9]{1,2};?){1,10})m)?
  2. Obsługuje WSZYSTKIE KOLORY i WSZYSTKIE OPCJE FORMATOWANIA TEKSTU, w tym pogrubienie, kursywa, przekreślenie itp., Które można ustawić w git configustawieniach . Dlatego powyższe wyrażenie regularne zawiera ;?i {1,10}: jeśli wykryje początek koloru lub kodu formatowania tekstu, dopasuje do 10 sekwencji tych połączonych kodów ANSI.
  3. NIE zawiera również wierszy zaczynających się od @@i słowa diff, jak to ma miejsce w zaakceptowanej odpowiedzi . Jeśli chcesz te linie (które szczerze mówiąc, myślę, że są przydatne :)), zrób to zamiast tego:

    git diff --unified=0
    

    lub

    git diff -U0
    
  4. Pokazuje dane wyjściowe w taki sam sposób, jak git diffbyłby to: na lesspagerze z opcjonalnym wyjściem kolorowym ( -R) i tylko wtedy, gdy tekst jest> 1 strona ( -F), i zachowując bieżącą stronę tekstu na ekranie, gdy qwykonujesz polecenie uit ( -X) .

Ma również tę zaletę, że jest potężny i łatwo konfigurowalny, ponieważ używa języka programowania awk.

Jeśli jesteś zainteresowany nauką awk , oto kilka zasobów:

  1. gawk(GNU awk) podręcznik: https://www.gnu.org/software/gawk/manual/html_node/index.html#SEC_Contents
  2. Badanie git diffni zamieszczone tam komentarze: https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles/blob/master/useful_scripts/git-diffn.sh
    1. Jeśli chcesz git diffn, czyli git diffz numerami linii, zobacz tutaj: Git diff z numerami linii (Git log z numerami linii)
  3. Niektóre przykłady testów awk „hello world” i testów składni: https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/tree/master/awk

Jako bonus git diffcdodałem również powyższe, aby użyć jako , co oznacza "git diff, aby pokazać TYLKO 'zmiany". Użycie jest identyczne z git diff; po prostu użyj git diffczamiast tego! Obsługuje WSZYSTKIE opcje. Kolor jest domyślnie WŁĄCZONY. Aby go wyłączyć, po prostu użyj git diffc --no-colorlub git diffc --color=never. Zobacz man git diffszczegóły.

Odkąd właśnie skończyłem wczoraj wieczorem git diffn(narzędzie do wyświetlania za git diffpomocą linii i liczb), pisanie git diffcbyło trywialne. Pomyślałem, że lepiej zrobię to teraz, kiedy wiedza jest świeża w mojej głowie.

Zainstaluj git diffc:

Postępuj zgodnie z instrukcjami na końcu tej odpowiedzi tutaj , z wyjątkiem wszystkich miejsc, które widzisz git-diffnw instrukcjach, użyj git-diffczamiast tego. Dotyczy to również wgetpolecenia. Pobieranie i instalowanie git diffcjest łatwe: to tylko kilka poleceń.

Gabriel Staples
źródło
0

Oto inny, prostszy sposób na znalezienie tylko tych wierszy, które zostały zmodyfikowane i dlatego zaczynają się od pojedynczego +lub- , zachowując kolor wyjściowy:

git diff -U0 --color=always HEAD~ | grep --color=never -E $'^\e\[(32m\+|31m-)'
  1. Plik -U0Mówi zawierać 0 linii kontekstu wokół zmienionych linii - czyli: obejmują tylko te zmieniły same linie. Zobacz man git diff.
  2. -EDla grep na to pozwala pracować z rozszerzonych wyrażeń regularnych
  3. $''Składnia najwyraźniej pozwala ANSI cytowanie, który poprawnie interpretuje ESC (escape lub 0x1b) Postać prawidłowo. Widzieć tutaj .
  4. A oto opis wyrażenia regularnego z https://www.regex101.com :wprowadź opis obrazu tutaj
  5. Zasadniczo ^dopasowuje początek wiersza, \edopasowuje znak Escape, który jest początkiem kodu koloru w terminalu, \[dopasowuje następny znak w kodzie koloru, czyli jest [, a następnie (this|that)składnia dopasowuje „to” lub „tamto” , gdzie to jest32m+ zielona linia +, a 31m-czerwona linia.
  6. Kolory są takie: \e[32mjest zielony i \e[31mjest czerwony.
  7. +pokazuje git diffoczywiście linie oznaczone jako dodane i -pokazuje linie oznaczonegit diff jako usunięte.
  8. Zauważ, że --color=neverjest wymagane w 2grep wyrażeniu, aby zapobiec podświetlaniu dopasowań, co w przeciwnym razie spieprzyłoby kody kolorów przychodzące od git difflewej strony.
  9. Należy +również wprowadzić zmiany znaczenia, \+ponieważ w przeciwnym razie +jest to specjalny znak wyrażenia regularnego (regex), który określa jedno lub więcej wystąpień poprzedniego elementu . Zobacz tutaj: https://en.wikipedia.org/wiki/Regular_expression#Basic_concepts .

Bibliografia:

  1. https://git-scm.com/docs/git-diff#_combined_diff_format
  2. Odpowiedź użytkownika @ user650654: Git diff, aby wyświetlić tylko zmodyfikowane wiersze
  3. Odpowiedź @wisbucky: Git diff, aby wyświetlić tylko zmodyfikowane wiersze

Związane z:

  1. [moja własna odpowiedź] Różnica Git z numerami linii (dziennik Git z numerami linii)
  2. [odpowiedź innej osoby] Różnica Git z numerami wierszy (dziennik Git z numerami wierszy)
  3. git diff z numerami linii i odpowiednim wyrównaniem / wcięciem kodu
  4. git-filechange-search.sh- skrypt, który pozwala przeszukać plik pod kątem nazwy zmiennej lub funkcji i dowiedzieć się, które zatwierdzenia zawierają zmiany o tej zmiennej lub nazwie funkcji. Dawny. użycie: ./git-filechange-search.sh path/to/my/file.cpp variable_nameznajdzie wszystkie zatwierdzenia ze zmianami w pliku.cpp, które się variable_namew nich zawierają . Jest to przydatne, aby zobaczyć, gdzie i kiedy zostały zmienione niektóre funkcje. To tak, jakby było to wyszukiwanie, które pozwala na obserwację sekcji pliku wyświetlanego git blamew czasie.
Gabriel Staples
źródło