Git diff per mostrare solo le linee che sono state modificate


128

Quando faccio un git diff, mostra le righe che sono state aggiunte:

+ this line is added

linee che sono state rimosse:

- this line is removed

ma mostra anche molte righe che non sono modificate:

this line is not modified
this line is also not modified

Ciò si traduce in un vero git diff simile a questo:

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

Posso chiedere a git di mostrare solo le righe che sono state modificate e ignorare tutti gli altri codici che non sono stati modificati? Ho scritto un metodo che rimuoverà tutte le righe che non hanno un segno "+" o "-" davanti a loro, ma sono sicuro che ci deve essere un modo più semplice per farlo.

Nel mio git diff, mi interessa solo vedere le linee che sono state modificate.

Grazie in anticipo.

Risposte:


182

Quello che vuoi è un diff con 0 righe di contesto. Puoi generarlo con:

git diff --unified=0

o

git diff -U0

Puoi anche impostarlo come opzione di configurazione per quel repository:

git config diff.context 0

Per impostarlo a livello globale, per qualsiasi repository:

 git config --global diff.context 0

4
Grazie per la rapida risposta. Questo risolve metà del mio problema ma sto ancora ottenendo alcune righe come "@@ -1 +1 @@" nel mio diff e nella parte superiore del mio git diff hanno "diff --git a / db / xxxxxxx b / db / xxxx index xxxxx..aaaaaaa bbbbbbbb
r3b00t

3
Non credo che git offra alcun modo per evitare di emettere quelle righe, perché il diff non avrebbe senso senza di esse (non si può sapere quale file si sta guardando, né dove si trovasse nel file).
Chris Hayes,

8
@Rakesh: per espandere, git-diff tenta di creare differenze che possono essere effettivamente utilizzate come patch per i file di origine, il che è impossibile senza tali informazioni. L'unico modo per rimuoverlo sarebbe post-elaborarlo da soli, come via git diff | egrep "^(\+|-) ".
Chris Hayes,

1
git config --global diff.context 0 per averlo ambientato a livello globale
Andrzej Rehmann,

Se vuoi vedere in una particolare directory prova git diff -U0 <dir>
Eswar Yaganti il

41

Un altro hack (su un * x) per mostrare solo le linee che iniziano con +e -:

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

Il codice sopra fa il seguente:

  • git diff -U0: scegli 0 linee di contesto
  • Il primo grep include solo tutte le linee che iniziano con +o-
  • Il secondo grep esclude le linee che iniziano con --- a/o+++ b/

Colore

Per mostrare il diff colorato, prova quanto segue:

git diff -U0 --color | grep '^\e\[[^m]*m[-+]' | grep -Ev '(--- a/|\+\+\+ b/)'
  • L'espressione, ^\e\[[^m]*m[-+]cerca l'inizio della riga ( ^), quindi il carattere di escape ( \e) seguito dal [quale iniziano insieme la sequenza di escape, quindi qualsiasi carattere che non sia una "m" (numeri, punti e virgola o nulla), seguito da un " m "che termina la sequenza di escape.
  • Nota che tutte le seguenti sono sequenze di escape valide: \e[0m(reset), \e[m(reset anche), \e[1m(grassetto acceso), \e[31m(rosso), \e[32m(verde), \e[9;31m(barrato + rosso), \e[31;9m(rosso + barrato), \e[1;4;9;31m(grassetto + sottolineato + barrato + rosso). I colori git predefiniti usano il rosso e il verde, ma possono essere riconfigurati.
  • --colorè lo stesso di --color=always.
  • La restrizione su --- a/o +++ b/apparire all'inizio della linea è stata rimossa per adattarsi alle sequenze di escape e questo potrebbe portare ad un caso limite.

Note aggiuntive:

  • La soluzione di cui sopra deve essere modificata se si utilizzano altre opzioni git diff, come -R, --src-prefix, --dst-prefix, --no-prefix, etc.
  • Le due grep possono essere combinate in una singola grep -E -v '^(\+\+\+ b/|--- a/|@@ |diff --git|index )', ma trovo che la versione a doppia grep sia più facile da capire.

2
Ben fatto. Valorizza la spiegazione chiara su ciascun filtro.
henrebotha,

Vedo molte git diffrighe di tipo "header" che iniziano con @@, ma quali sono le git diffrighe che iniziano con ---o +++? Non ne ero a conoscenza.
Gabriel Staples

Ah, non importa. Indicano i nomi dei file per i file che contengono addizioni ( +++) o eliminazioni ( ---). Lo vedo qui ora: git-scm.com/docs/git-diff#_combined_diff_format .
Gabriel Staples

Correzione ancora: --- a/filenamesembra indicare il "file a sinistra", o il file com'era prima, e +++ b/filenamesembra indicare il "file a destra", o il file come è ora con le modifiche. Sono così abituato a usare git difftoolcon Meld , che mostra bellissimi confronti affiancati, che non mi sono mai abituato a guardare git diff, quindi mi sembra ancora strano e non ho mai visto prima queste sfumature.
Gabriel Staples

1
@GabrielStaples, è stato aggiunto il supporto per il colore. Grazie.
user650654,

6

In seguito all'ultimo commento di Chris, il problema principale con la post-elaborazione è che si desidera mantenere le linee con cui iniziare -|+ma anche filtrare quelle che iniziano con ---|+++. Se stai memorizzando i file patch nel tuo repository (lo faccio, in Pydoop ), d'altra parte, vuoi mantenere le linee che iniziano con --|++, quindi il regexp diventa un po 'coinvolto:

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

Il regexp usa uno sguardo negativo: vedi la risposta di Peter Boughton a questa domanda per una spiegazione dettagliata.

Se lo fai spesso, potresti voler impostare un alias git per questo:

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

1
questo non ha funzionato per me su Windows Git Bash. Non so perché (grep ha dichiarato l'opzione P non valida), al momento non ho la faccia tosta.
Dennis,

1
-Po --perl-regexpviene utilizzato per interpretare il modello come una rexpressione regolare Perl, ma non viene sempre implementato. Non ha funzionato per me su OSX. gnu.org/software/grep/manual/grep.html#grep-Programs
Willington Vega

5

Penso che per casi semplici il regex può essere molto più breve e più facile da ricordare, con l'avvertenza che questo non funzionerà se ci sono cambiamenti di linea dove inizia la linea stessa +o-

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

Il regex dice che la linea dovrebbe iniziare con +o -, e il carattere immediatamente successivo non dovrebbe essere nessuno di questi. Ho ottenuto gli stessi risultati, sia che fossi scappato +o no qui, a proposito ...


Esempio:

$ cat testfile
A
B
C
D
E
F
G

Di 'che cambio Ca X, Ea Ye Ga Z.

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

Come ho detto sopra, però, questo è solo per la maggior parte dei casi. Se installi l'output in un file dout, quindi prova la stessa regex, non funzionerà.

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

Spero comunque che ti aiuti nel tuo caso


Per i casi in cui la linea inizia con "-" non funzionerà. Esempio: - name: No pdbin un file yaml.
anapaulagomes,

3

Questa risposta manterrà i colori rosso / verde originali per la leggibilità. Ho fornito alcune varianti nella sintassi:

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'

Spiegazione:

  • Il git diff --colorche serve per impedire git di disattivare il colore quando viene tubazioni.
  • Il grep --color=neverè quello di prevenire grep rimozione del colore originale e mettendo in evidenza la stringa corrispondente.
  • Stiamo eseguendo la corrispondenza per le linee che iniziano con codici di escape rossi ( \e[31m) o verdi ( \e[32m).
  • La $'...'(sintassi di citazione ANSI-C) o -P(sintassi perl) è di lasciare grepinterpretare \eo \033come ESCcarattere.

Grazie per questo. Ecco un modulo alternativo che ho appena inventato. La tua $''parte mi ha aiutato in modo particolare. stackoverflow.com/a/61929887/4561887
Gabriel Staples

1

Come utilizzare awkper mostrare solo le linee +e -, tenendo conto di qualsiasi colore o formattazione del testo git diffpotrebbe essere in uscita:

Nessuna delle altre risposte qui (inclusa la mia altra risposta ) farà esattamente quello che vuoi correttamente al 100%. Questa risposta, tuttavia, lo farà. Ecco un 1-liner che puoi copiare e incollare nel tuo terminale. Ho appena creato più righe per leggibilità: puoi copiarlo e incollarlo nello stesso modo in modo che io possa anche renderlo leggibile! Si basa sul awklinguaggio di programmazione:

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

Ecco le sue caratteristiche. Tutte queste caratteristiche, se messe insieme, risolvono le carenze di ogni altra risposta qui:

  1. Gestisce output a colori e senza colori. Ecco cosa fa questa espressione regolare:^(\033\[(([0-9]{1,2};?){1,10})m)?
  2. Gestisce TUTTI I COLORI e TUTTE LE OPZIONI DI FORMATTAZIONE DEL TESTO, tra cui grassetto, corsivo, barrato, ecc., Che è possibile impostare nelle git configimpostazioni . Ecco perché la regex sopra ha ;?e {1,10}in essa: se rileva l'inizio di un codice di formattazione di colore o testo, corrisponderà a un massimo di 10 sequenze di questi codici ANSI combinati.
  3. NON include anche le righe che iniziano con @@e la parola diff, come fa la risposta accettata . Se vuoi quelle righe (che francamente, penso che siano utili :)), invece fai questo:

    git diff --unified=0
    

    o

    git diff -U0
    
  4. Mostra l'output nello stesso modo esatto git diff: nel lesscercapersone con output a colori opzionale ( -R), e solo se il testo è> 1 pagina ( -F) e mantenendo la pagina corrente di testo sullo schermo quando si qusa ( -X) .

Ha anche il vantaggio di essere potente e facilmente configurabile poiché utilizza il linguaggio di programmazione awk.

Se sei interessato a imparare awk , ecco alcune risorse:

  1. gawk(GNU awk) manuale: https://www.gnu.org/software/gawk/manual/html_node/index.html#SEC_Contents
  2. Studio git diffne relativi commenti: https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles/blob/master/useful_scripts/git-diffn.sh
    1. Se vuoi git diffnanche, che è git diffcon i numeri di riga, vedi qui: Git diff con i numeri di riga (Git log con i numeri di riga)
  3. Alcuni esempi di test "hello world" e di sintassi: https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/tree/master/awk

Come bonus, ho anche concluso quanto sopra da usare come git diffc, il che significa "git diff per mostrare SOLO 'c'hanges". L'uso è identico a git diff; basta usare git diffcinvece! Supporta TUTTE le opzioni. Il colore è ON per impostazione predefinita. Per disattivarlo, utilizzare semplicemente git diffc --no-coloro git diffc --color=never. Vedi man git diffper i dettagli.

Da quando ho appena finito git diffn(uno strumento per mostrare git diffcon line 'n'umbers) ieri sera, scrivere è git diffcstato banale. Ho pensato che sarebbe meglio farlo ora mentre la conoscenza è fresca nella mia testa.

Installa git diffc:

Segui le istruzioni alla fine di questa risposta qui , tranne che ovunque tu veda git-diffnnelle istruzioni, usa git-diffcinvece. Ciò include anche nel wgetcomando. Scaricare e installare git diffcè semplice: bastano pochi comandi.


0

Ecco un altro modo più semplice per trovare solo le linee che sono state modificate, e quindi iniziare con un singolo +o -, pur mantenendo l'output del colore:

git diff -U0 --color=always HEAD~ | grep --color=never -E $'^\e\[(32m\+|31m-)'
  1. La -U0dice per includere 0 righe di contesto attorno alle linee modificate - vale a dire: include solo le linee modificate stessi. Vedere man git diff.
  2. Il -Eper grep consente di lavorare con le espressioni regolari estese
  3. La $''sintassi apparentemente consente la quotazione ANSI, che interpreta correttamente il carattere ESC (escape o 0x1b). Vedi qui .
  4. Ed ecco la descrizione di regex da https://www.regex101.com :inserisci qui la descrizione dell'immagine
  5. Fondamentalmente, ^corrisponde all'inizio della riga, \ecorrisponde al carattere Escape, che è l'inizio di un codice colore nel terminale, \[corrisponde al carattere successivo nel codice colore, che è [, quindi la (this|that)sintassi corrisponde a "questo" o "quello" , dove "this" è 32m+, che è una linea verde + ed 31m-è una linea rossa.
  6. I colori sono così: \e[32mè verde ed \e[31mè rosso.
  7. +mostra le linee contrassegnate git diffcome aggiunte, ovviamente, e -mostra le linee contrassegnate git diffcome eliminate.
  8. Si noti che --color=neverè necessario nella seconda grepespressione per evitare che evidenzi le sue corrispondenze, che altrimenti rovinerebbero i codici colore che arrivano da git diffsinistra.
  9. La +deve essere sfuggito anche come \+perché altrimenti la +è un carattere speciale espressione regolare (regex) che specifica una o più occorrenze dell'elemento precedente . Vedi qui: https://en.wikipedia.org/wiki/Regular_expression#Basic_concepts .

Riferimenti:

  1. https://git-scm.com/docs/git-diff#_combined_diff_format
  2. Risposta di @ user650654: Git diff per mostrare solo le righe che sono state modificate
  3. Risposta di @wisbucky: Git diff per mostrare solo le righe che sono state modificate

Relazionato:

  1. [la mia risposta] Git diff con numeri di riga (Git log con numeri di riga)
  2. [la risposta di qualcun altro] Git diff con i numeri di riga (Git log con i numeri di riga)
  3. git diff con i numeri di riga e il corretto allineamento / rientro del codice
  4. git-filechange-search.sh- uno script che consente di cercare in un file un nome di variabile o funzione e di capire quali commit contengono modifiche con tale nome di variabile o funzione. Ex. utilizzo: ./git-filechange-search.sh path/to/my/file.cpp variable_nametroverà tutti i commit con le modifiche a file.cpp che contengono variable_namein essi. Questo è utile per vedere dove e quando sono state modificate alcune funzionalità. È come se fosse una ricerca in grado di osservare sezioni di un file visualizzate git blamenel tempo.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.