Git diff pour afficher uniquement les lignes qui ont été modifiées

128

Quand je fais un git diff, il montre les lignes qui ont été ajoutées:

+ this line is added

lignes qui ont été supprimées:

- this line is removed

mais il montre aussi de nombreuses lignes qui ne sont pas modifiées:

this line is not modified
this line is also not modified

Cela donne au diff réel git ressemblant à ceci:

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

Puis-je demander à git de n'afficher que les lignes qui ont été modifiées et d'ignorer tout autre code qui n'a pas été modifié? J'ai écrit une méthode qui supprimera toutes les lignes qui n'ont pas de signe «+» ou «-» devant elles, mais je suis sûr qu'il doit y avoir un moyen plus simple de le faire.

Dans mon git diff, je ne suis intéressé que par les lignes qui ont été modifiées.

Merci d'avance.

r3b00t
la source

Réponses:

182

Ce que vous voulez, c'est un diff avec 0 lignes de contexte. Vous pouvez générer ceci avec:

git diff --unified=0

ou

git diff -U0

Vous pouvez également définir cela comme une option de configuration pour ce référentiel:

git config diff.context 0

Pour l'avoir défini globalement, pour n'importe quel référentiel:

 git config --global diff.context 0
Chris Hayes
la source
4
Merci pour votre réponse rapide. Cela résout la moitié de mon problème mais j'obtiens toujours des lignes comme "@@ -1 +1 @@" dans mon diff et le haut de mon git diff ont "diff --git a / db / xxxxxxx b / db / xxxx index xxxxx..aaaaaaa bbbbbbbb
r3b00t
3
Je ne pense pas que git offre un moyen d'éviter de sortir ces lignes, car le diff n'aurait aucun sens sans elles (vous ne pouviez pas savoir quel fichier vous regardiez, ni où vous étiez dans le fichier).
Chris Hayes
8
@Rakesh: Pour se développer, git-diff tente de créer des différences qui peuvent en fait être utilisées comme correctifs pour les fichiers source, ce qui est impossible sans ces informations. Le seul moyen de le supprimer serait de le post-traiter vous-même, par exemple via git diff | egrep "^(\+|-) ".
Chris Hayes
1
git config --global diff.context 0 pour l'avoir réglé globalement
Andrzej Rehmann
Si vous voulez voir dans un répertoire particulier, essayez git diff -U0 <dir>
Eswar Yaganti
41

Un autre hack (sur un * x) pour afficher uniquement les lignes commençant par +et -:

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

Le code ci-dessus effectue les opérations suivantes:

  • git diff -U0: choisissez 0 ligne de contexte
  • Le premier grep inclut uniquement toutes les lignes commençant par +ou-
  • Le second grep exclut les lignes commençant par --- a/ou+++ b/

Couleur

Pour afficher des différences colorées, essayez ce qui suit:

git diff -U0 --color | grep '^\e\[[^m]*m[-+]' | grep -Ev '(--- a/|\+\+\+ b/)'
  • L'expression ^\e\[[^m]*m[-+],, recherche le début de la ligne ( ^), puis le caractère d'échappement ( \e) suivi par [lequel ensemble commence la séquence d'échappement, puis tout caractère qui n'est pas un "m" (nombres, points-virgules ou rien), suivi d'un " m "qui termine la séquence d'échappement.
  • Notez que tous les éléments suivants sont des séquences d'échappement valides: \e[0m(réinitialiser), \e[m(également réinitialiser), \e[1m(gras activé), \e[31m(rouge), \e[32m(vert), \e[9;31m(barré + rouge), \e[31;9m(rouge + barré), \e[1;4;9;31m(gras + souligné + barré + rouge). Les couleurs git par défaut utilisent le rouge et le vert, mais elles peuvent être reconfigurées.
  • --colorest le même que --color=always.
  • La restriction sur --- a/ou +++ b/à apparaître au début de la ligne a été supprimée pour tenir compte des séquences d'échappement et cela pourrait conduire à un cas de bord.

Notes complémentaires:

  • La solution ci - dessus doit être modifiée si vous utilisez les options git diff supplémentaires telles que -R, --src-prefix, --dst-prefix, --no-prefix, etc.
  • Les deux greps peuvent être combinés en un seul grep -E -v '^(\+\+\+ b/|--- a/|@@ |diff --git|index )', mais je trouve la version double grep plus facile à comprendre.
user650654
la source
2
Joli. Votez pour l'explication claire de chaque filtre.
henrebotha
Je vois beaucoup de git difflignes de type "en-tête" qui commencent par @@, mais que sont les git difflignes qui commencent par ---ou +++? Je n'étais pas au courant de ceux-là.
Gabriel Staples
Ah laisse tomber. Ceux-ci indiquent les noms de fichiers pour les fichiers qui contiennent des additions ( +++) ou des suppressions ( ---). Je vois cela ici maintenant: git-scm.com/docs/git-diff#_combined_diff_format .
Gabriel Staples
Correction encore une fois: --- a/filenamesemble désigner le "fichier à gauche", ou le fichier tel qu'il était avant, et +++ b/filenamesemble désigner le "fichier à droite", ou le fichier tel qu'il est maintenant avec vos modifications. Je suis tellement habitué à utiliser git difftoolavec meld , qui montre de belles comparaisons côte à côte, que je ne me suis jamais vraiment habitué à regarder git diff, donc cela me semble toujours étrange, et je n'ai jamais vraiment regardé ces nuances auparavant.
Gabriel Staples
1
@GabrielStaples, la prise en charge de la couleur a été ajoutée. Merci.
user650654
6

Suite au dernier commentaire de Chris, le principal problème avec le post-traitement est que vous voulez garder les lignes commençant par -|+mais vous voulez également filtrer celles qui commencent par ---|+++. Si vous stockez des fichiers de correctifs dans votre dépôt (je le fais, dans Pydoop ), par contre, vous voulez garder les lignes commençant par --|++, donc l'expression rationnelle devient un peu impliquée:

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

L'expression régulière utilise une anticipation négative: voir la réponse de Peter Boughton à cette question pour une explication détaillée.

Si vous faites cela souvent, vous voudrez peut-être configurer un alias git pour cela:

git config --global alias.diffonly '!git diff | grep -P "^\+(?:(?!\+\+))|^-(?:(?!--))"'
Simleo
la source
1
cela n'a pas fonctionné pour moi sur Windows git bash. Je ne sais pas pourquoi (grep a dit l'option P invalide), je n'ai pas le chutzpah de l'examiner pour le moment.
Dennis
1
-Pou --perl-regexpest utilisé pour interpréter le modèle comme une expression régulière Perl, mais n'est pas toujours implémenté. Cela n'a pas fonctionné pour moi sur OSX. gnu.org/software/grep/manual/grep.html#grep-Programs
Willington Vega
5

Je pense que pour les cas simples, l'expression régulière peut être beaucoup plus courte et plus facile à retenir, avec la mise en garde que cela ne fonctionnera pas si vous avez des changements de ligne où la ligne elle-même commence par +ou-

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

L'expression régulière dit que la ligne doit commencer par +ou -, et le caractère immédiatement suivant ne doit être ni l'un ni l'autre. J'ai eu les mêmes résultats que je me sois échappé +ou pas ici, au fait ...


Exemple:

$ cat testfile
A
B
C
D
E
F
G

Dites que je change Cen X, Een Yet Gen Z.

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

Comme je l'ai dit ci-dessus, cependant, c'est juste pour la plupart des cas. Si vous dirigez cette sortie vers un fichier dout, puis essayez la même expression régulière, cela ne fonctionnera pas.

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

Quoi qu'il en soit, j'espère que cela vous aidera dans votre cas

galois
la source
Dans les cas où la ligne commence par "-", cela ne fonctionnera pas. Exemple: - name: No pdbdans un fichier yaml.
anapaulagomes
3

Cette réponse conservera les couleurs rouges / vertes d'origine pour plus de lisibilité. J'ai fourni quelques variations de syntaxe:

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'

Explication:

  • Le git diff --colorest nécessaire pour empêcher git de désactiver la couleur lors de la mise en réseau.
  • Le but grep --color=neverest d'empêcher grep de supprimer la couleur d'origine et de mettre en évidence la chaîne correspondante.
  • Nous recherchons des lignes commençant par des codes d'échappement rouge ( \e[31m) ou vert ( \e[32m).
  • La $'...'(syntaxe des guillemets ANSI-C) ou la -P(syntaxe perl) est à laisser grepinterpréter \eou \033comme un ESCcaractère.
wisbucky
la source
Merci pour cela. Voici une forme alternative que je viens de proposer. Votre $''rôle m'a particulièrement aidé. stackoverflow.com/a/61929887/4561887
Gabriel Staples
1

Comment utiliser awkpour afficher uniquement les lignes +et -, en tenant compte de toute couleur ou de la mise en forme du texte git diff:

Pas une seule des autres réponses ici (y compris mon autre réponse ) ne fera exactement ce que vous voulez à 100% correctement. Cette réponse, cependant, le sera. Voici un 1-liner que vous pouvez copier et coller dans votre terminal.Je viens de le faire en plusieurs lignes pour plus de lisibilité - vous pouvez le copier-coller de la même manière, donc je ferais aussi bien de le rendre lisible! Il repose sur le awklangage de programmation:

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

Voici ses caractéristiques. Toutes ces fonctionnalités, prises ensemble, résolvent les lacunes de toutes les autres réponses ici:

  1. Il gère la sortie couleur ET sans couleur. C'est ce que fait cette expression régulière:^(\033\[(([0-9]{1,2};?){1,10})m)?
  2. Il gère TOUTES LES COULEURS et TOUTES LES OPTIONS DE FORMATAGE DE TEXTE, y compris le gras, l'italique, le barré, etc., que vous pouvez définir dans vos git configparamètres . C'est pourquoi le regex ci-dessus a;? et{1,10} : s'il détecte le début d'un code de formatage de couleur ou de texte, il correspondra à jusqu'à 10 séquences de ces codes ANSI combinés.
  3. Il n'inclut PAS également les lignes commençant par @@et le mot diff, comme le fait la réponse acceptée . Si vous voulez ces lignes (qui, franchement, je pense qu'elles sont utiles :)), faites ceci à la place:

    git diff --unified=0
    

    ou

    git diff -U0
    
  4. Il affiche la sortie de la même manière exacte que le git diffferait: dans le lesspager avec sortie couleur optionnelle ( -R), et seulement si le texte est> 1 page ( -F), et tout en conservant la page de texte actuelle à l'écran lorsque vous quit ( -X) .

Il a également l'avantage d'être puissant et facilement configurable car il utilise le langage de programmation awk.

Si vous souhaitez apprendre awk , voici quelques ressources:

  1. gawk(GNU awk) manuel: https://www.gnu.org/software/gawk/manual/html_node/index.html#SEC_Contents
  2. Étude git diffnet commentaires y afférents : https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles/blob/master/useful_scripts/git-diffn.sh
    1. Si vous voulez git diffnaussi, qui est git diffavec les numéros de ligne, voir ici: Git diff avec les numéros de ligne (Git log avec les numéros de ligne)
  3. Quelques exemples de tests de syntaxe et de «bonjour le monde» awk: https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/tree/master/awk

En prime, j'ai également résumé ce qui précède pour être utilisé comme git diffc, ce qui signifie "git diff pour afficher UNIQUEMENT les 'c'hanges". L'utilisation est identique à git diff; utilisez simplement à la git diffcplace! Il prend en charge TOUTES les options. La couleur est activée par défaut. Pour le désactiver, utilisez simplement git diffc --no-colorou git diffc --color=never. Voir man git diffpour plus de détails.

Depuis que je viens de terminer git diffn(un outil à afficher git diffavec des numéros de lignes) hier soir, l'écriture git diffcétait triviale. J'ai pensé que je ferais mieux de le faire maintenant pendant que les connaissances sont fraîches dans ma tête.

Installer git diffc:

Suivez les instructions à la fin de cette réponse ici , sauf partout où vous voyez git-diffndans les instructions, utilisez git-diffcplutôt. Cela inclut aussi dans la wgetcommande. Le téléchargement et l'installation git diffcsont faciles: il ne s'agit que de quelques commandes.

Gabriel Staples
la source
0

Voici un autre moyen plus simple de rechercher uniquement les lignes qui ont été modifiées, et donc de commencer par un seul +ou -, tout en conservant la sortie couleur:

git diff -U0 --color=always HEAD~ | grep --color=never -E $'^\e\[(32m\+|31m-)'
  1. Le -U0dit d'inclure 0 lignes de contexte autour des lignes modifiées - c'est-à-dire: inclure uniquement les lignes modifiées elles-mêmes. Voir man git diff.
  2. Le -Efor grep lui permet de travailler avec des expressions régulières étendues
  3. La $''syntaxe autorise apparemment les guillemets ANSI, qui interprètent correctement le caractère ESC (escape ou 0x1b). Regardez ici .
  4. Et voici la description regex de https://www.regex101.com :entrez la description de l'image ici
  5. Fondamentalement, ^correspond au début de la ligne, \ecorrespond au caractère d'échappement, qui est le début d'un code de couleur dans le terminal, \[correspond au caractère suivant dans le code de couleur, qui est [, puis la (this|that)syntaxe correspond à "ceci" ou "cela" , où "this" est 32m+, qui est une ligne + verte, et31m- est une ligne rouge.
  6. Les couleurs sont comme ceci: \e[32mest vert et \e[31mest rouge.
  7. +affiche les lignes marquées par git diffcomme ajoutées, bien sûr, et -affiche les lignes marquées par git diffcomme supprimées.
  8. Notez que cela --color=neverest obligatoire dans la 2ème grepexpression afin de l'empêcher de mettre en évidence ses correspondances, ce qui sinon bousillerait les codes de couleur venant de git diffla gauche.
  9. Le +doit également être échappé \+car sinon, il +s'agit d'un caractère d'expression régulière (regex) spécial qui spécifie une ou plusieurs occurrences de l'élément précédent . Voir ici: https://en.wikipedia.org/wiki/Regular_expression#Basic_concepts .

Références:

  1. https://git-scm.com/docs/git-diff#_combined_diff_format
  2. Réponse de @ user650654: Git diff pour afficher uniquement les lignes qui ont été modifiées
  3. Réponse de @wisbucky: Git diff pour afficher uniquement les lignes qui ont été modifiées

En relation:

  1. [ma propre réponse] Git diff avec les numéros de ligne (Git log avec les numéros de ligne)
  2. [réponse de quelqu'un d'autre] Git diff avec numéros de ligne (journal Git avec numéros de ligne)
  3. git diff avec les numéros de ligne et l'alignement / l'indentation du code approprié
  4. git-filechange-search.sh- un script qui vous permet de rechercher dans un fichier un nom de variable ou de fonction et de déterminer quels commits contiennent des modifications avec ce nom de variable ou de fonction. Ex. utilisation: ./git-filechange-search.sh path/to/my/file.cpp variable_nametrouvera tous les commits avec les modifications apportées à file.cpp qui les contiennent variable_name. Ceci est utile pour voir où et quand certaines fonctionnalités ont été modifiées. C'est comme s'il s'agissait d'une recherche permettant d'observer des sections d'un fichier affichées via au git blamefil du temps.
Gabriel Staples
la source