Git diff avec numéros de ligne (journal Git avec numéros de ligne)

92

Lorsque je fais a git diffou a git log -p, comment puis-je obtenir les numéros de ligne du (des) fichier (s) source (s) en ligne avec la sortie?

J'ai essayé de le rechercher man git-diff | grep "line numbers"et j'ai essayé de googler mais je n'ai rien obtenu rapidement.

Drew LeSueur
la source

Réponses:

90

Vous ne pouvez pas obtenir de numéros de ligne lisibles par l'homme avec git diff

Il n'y a actuellement aucune option pour afficher les numéros de ligne verticalement sur le côté avec git diff.

Format de diff unifié

Ces informations sont disponibles dans les en-têtes (c) hunk pour chaque changement dans le diff, mais c'est juste au format unifié-diff :

@@ -start,count +start,count @@

L'état d'origine du fichier est représenté par -, et le nouvel état est représenté par +(ils ne signifient pas des ajouts et des suppressions dans l'en-tête de morceau. startReprésente le numéro de ligne de départ de chaque version du fichier, et countreprésente le nombre de lignes incluses , à partir du point de départ.

Exemple

diff --git a/osx/.gitconfig b/osx/.gitconfig
index 4fd8f04..fcd220c 100644
--- a/osx/.gitconfig
+++ b/osx/.gitconfig
@@ -11,7 +11,7 @@ <== HERE!
 [color "branch"]
        upstream = cyan
 [color "diff"]
-       meta = yellow
+       meta = cyan
        plain = white dim
        old = red bold
        new = green bold

L'en-tête du morceau

@@ -11,7 +11,7 @@

indique que la version précédente du fichier commence à la ligne 11 et comprend 7 lignes:

11  [color "branch"]
12         upstream = cyan
13  [color "diff"]
14 -       meta = yellow
14 +       meta = cyan
15         plain = white dim
16         old = red bold
17         new = green bold

tandis que la prochaine version du fichier commence également à la ligne 11 et comprend également 7 lignes.

Le format de diff unifié n'est pas vraiment destiné à la consommation humaine

Comme vous pouvez probablement le constater, le format diff unifié ne facilite pas la détermination des numéros de ligne (du moins si vous n'êtes pas une machine). Si vous voulez vraiment des numéros de ligne que vous pouvez lire, vous devrez utiliser un outil différent qui les affichera pour vous.

Lecture supplémentaire

Khalid
la source
3
Voici un grep pour extraire uniquement les numéros de ligne dans les fichiers modifiés, par exemple pour être utilisé pour filtrer un rapport de checkstylegit diff --unified=0 | grep -Po '^\+\+\+ ./\K.*|^@@ -[0-9]+(,[0-9]+)? \+\K[0-9]+(,[0-9]+)?(?= @@)'
Jakub Bochenski
1
Le commentaire de @ JakubBochenski a très bien résolu mon problème.
0xbe5077 du
Ceci n'est vraiment utile que si vous spécifiez --unified=0ou -U0, cependant.
caw
Je viens de terminer git diffn, un remplacement instantané (wrapper) pour git difflequel affiche les numéros de ligne et a une compatibilité totale avec toutes les utilisations et options de git diff: stackoverflow.com/questions/24455377/...
Gabriel Staples
22

Voici deux autres solutions, développant le code d'Andy Talkowski.

Texte brut:

  git diff | gawk 'match($0,"^@@ -([0-9]+),[0-9]+ [+]([0-9]+),[0-9]+ @@",a){left=a[1];right=a[2];next};\
   /^(---|\+\+\+|[^-+ ])/{print;next};\
   {line=substr($0,2)};\
   /^-/{print "-" left++ ":" line;next};\
   /^[+]/{print "+" right++ ":" line;next};\
   {print "(" left++ "," right++ "):"line}'

Texte coloré, en supposant que \033[66mle format des codes couleur:

  git diff --color=always | \
    gawk '{bare=$0;gsub("\033[[][0-9]*m","",bare)};\
      match(bare,"^@@ -([0-9]+),[0-9]+ [+]([0-9]+),[0-9]+ @@",a){left=a[1];right=a[2];next};\
      bare ~ /^(---|\+\+\+|[^-+ ])/{print;next};\
      {line=gensub("^(\033[[][0-9]*m)?(.)","\\2\\1",1,$0)};\
      bare~/^-/{print "-"left++ ":" line;next};\
      bare~/^[+]/{print "+"right++ ":" line;next};\
      {print "("left++","right++"):"line;next}'

Le code modifie les lignes qui commencent par -et +à -1:-et +1:+, respectivement, et les lignes qui commencent par rien à (5,6):. Les numéros sont les numéros de ligne du fichier respectif.

PFudd
la source
Je remarque qu'il rompt l'alignement (indentation) du code, alors que le natif git diffmaintient soigneusement l'alignement. Ce code est au-dessus de ma tête pour le moment, seriez-vous prêt à le réparer? En d'autres termes, lorsqu'une ligne dit +240:+et la ligne suivante dit (241,257):, vous devez ajouter des espaces supplémentaires à la ligne supérieure pour que son code conserve un alignement et une indentation appropriés avec le code de la ligne inférieure. Peut-être que cela pourrait facilement être fait avec l'impression?
Gabriel Staples
... je veux dire avec printf.
Gabriel Staples
Ça ne fait rien; J? ai compris! Je viens de terminer git diffn. Voir ici: stackoverflow.com/a/61997003/4561887 . Merci @PFudd, pour votre réponse. Je l'ai étudié et utilisé pour apprendre, puis je suis parti de zéro et j'ai écrit git diffn. Une fois formaté pour pouvoir lire votre code (merci @EdMorton), j'ai pu en apprendre de très bonnes choses qui m'ont aidé.
Gabriel Staples
6

Voici un script qui tente de résoudre ce problème - pas testé avec colère, mais cela semble correct. Il s'appuie sur les enregistrements que git diff produit et utilise awk pour maintenir le nombre de lignes.

# Massage the @@ counts so they are usable
function prep1() {
   cat | awk -F',' 'BEGIN { convert = 0; }
       /^@@ / { convert=1; }
       /^/  { if ( convert == 1 ) { print $1,$2,$3;
              } else { print $0;
              }
              convert=0;
             }'
}

# Extract all new changes added with the line count
function prep2() {
  cat | awk 'BEGIN { display=0; line=0; left=0; out=1;}
     /^@@ / { out=0; inc=0; line=$4; line--; display=line; left=line;        }
     /^[-]/   { left++; display=left; inc=0; }
     /^[+]/   { line++; display=line; inc=0; }
     /^[-+][-+][-+] / { out=0; inc=0; }
     /^/    { 
               line += inc;
               left += inc;
               display += inc;
               if ( out == 1 ) {
                   print display,$0;
               } else {
                   print $0;
               }
               out = 1;
               inc = 1;
               display = line;
            }'
} 

git diff $1 | prep1 | prep2 
Andy Talkowski
la source
4

Vous pouvez utiliser git difftoolpour faire la différence avec un éditeur externe qui affichera les numéros de ligne. Voici comment le faire avec vim / vimdiff:

  1. Définissez vimdiff comme difftool de git:

    git config --global diff.tool vimdiff
    
  2. Configurez ~/.vimrcpour afficher automatiquement les numéros de ligne lors de l'utilisation de vimdiff:

    if &diff
        set number
    endif
    
  3. Exécutez git difftool, qui utilisera vimdiff avec les numéros de ligne:

    git difftool
    
wisbucky
la source
En ne faisant que git difftool, il m'a ouvert l'outil tkdiff, qui lui-même a la fonction de numéro de ligne. Merci wisbucky
Richardd
3

Un moyen rapide consiste à utiliser git diff -U0. Cela définira les lignes de contexte sur 0, ce qui fera correspondre les valeurs @@ aux lignes réellement modifiées. Par défaut, les valeurs @@ incluent 3 lignes de contexte avant / après, ce qui n'est pas pratique pour les humains.

Exemple:

git diff # default
@@ -10,8 +10,8 @@

Il est difficile de calculer les numéros de ligne des lignes modifiées car la ligne 10 fait référence à la première ligne du contexte avant. Le numéro de ligne réel de la première ligne modifiée est 10 + 3 = 13. Pour calculer le nombre de lignes modifiées, vous devez également soustraire le contexte avant et après: 8-3-3 = 2.

git diff -U0
@@ -13,2 +13,2 @@

Comme vous pouvez le voir, la définition de context = 0 facilite la lecture des valeurs @@ par les humains. Vous pouvez voir que les lignes modifiées commencent à la ligne 13 et qu'il y a 2 lignes modifiées.

Ce n'est pas parfait, car il ne montre que le numéro de ligne pour chaque bloc. Si vous voulez voir les numéros de ligne pour chaque ligne, utilisez difftool pour un éditeur externe. Voir https://stackoverflow.com/a/50049752

wisbucky
la source
3

J'aime utiliser git difftoolavec meld comme difftool. Il est plus facile à regarder que git diff, a une belle comparaison d'interface graphique côte à côte et affiche les numéros de ligne de chaque côté.

Installer:

  1. Instructions sur la configuration de meld en tant que difftool pour Windows ou Linux

Exemple de capture d'écran:

entrez la description de l'image ici

Mise à jour du 24 mai 2020:

Je viens d'écrire au git diffncours des derniers jours pour remplacer git diffla ligne de commande. Donner un coup de feu. Voir mon autre réponse ici .

Gabriel Staples
la source
2

Depuis le 24 mai 2020, vous pouvez désormais utiliser l'outil tiers git diffn(divulgation complète: je l'ai écrit) à cette fin. C'est un wrapper léger git diff, écrit dans le awklangage de programmation basé sur des modèles / actions. Voici un exemple de sortie de l'exécution git diffn:

entrez la description de l'image ici

Voici une démo:

1/3: Démo de git diffn:

Créez ce fichier:

bonjour_world.c:

#include <stdio.h>

int main()
{
    printf("Hello World\n");

    return 0;
}

Engagez-le:

git add hello_world.c
git commit -m "add hello_world.c"

Modifiez-le et enregistrez le fichier:

bonjour_world.c:

// Basic hello world example

#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("Hello Gabriel\n");
    
    int i = 700;
    printf("i = %i\n", i);
    return 0;
}

Maintenant, exécutez:

git diff

Voici la sortie de git diff first à des fins de comparaison:

$ git diff
diff --git a/hello_world.c b/hello_world.c
index e01704a..e971b73 100644
--- a/hello_world.c
+++ b/hello_world.c
@@ -1,8 +1,12 @@
+// Basic hello world example
+
 #include <stdio.h>
 
-int main()
+int main(int argc, char *argv[])
 {
-    printf("Hello World\n");
-
+    printf("Hello Gabriel\n");
+    
+    int i = 700;
+    printf("i = %i\n", i);
     return 0;
-}
\ No newline at end of file
+}

Et une capture d'écran pour montrer la couleur. Notez que la section en surbrillance rouge montre simplement des espaces vides (espaces dans ce cas) qui pourraient être supprimés:

entrez la description de l'image ici

Voici maintenant la sortie de git diffn . Remarquez qu'il montre parfaitement tous les numéros de ligne!

  • Les numéros de ligne des lignes supprimées sont sur la gauche et affichent un- signe à l'extrême gauche ET à droite du :pour vous aider à mieux voir - que vos yeux aiment balayer vers le bas à droite des deux points ou vers le bas à l'extrême à gauche de l'écran.
  • Les numéros de ligne des lignes ajoutées sont plus à droite et affichent un+ signe à la fois à l'extrême gauche ET à droite du :.
  • Les numéros de ligne des lignes inchangées affichées pour le contexte sont affichés à la fois pour la gauche (ancien fichier) ET pour la droite (nouveau fichier), séparés par un, .

Sortie de git diffn:

$ git diffn
diff --git a/hello_world.c b/hello_world.c
index e01704a..e971b73 100644
--- a/hello_world.c
+++ b/hello_world.c
@@ -1,8 +1,12 @@
+        1:+// Basic hello world example
+        2:+
    1,   3: #include <stdio.h>
    2,   4: 
-   3     :-int main()
+        5:+int main(int argc, char *argv[])
    4,   6: {
-   5     :-    printf("Hello World\n");
-   6     :-
+        7:+    printf("Hello Gabriel\n");
+        8:+    
+        9:+    int i = 700;
+       10:+    printf("i = %i\n", i);
    7,  11:     return 0;
-   8     :-}
\ No newline at end of file
+       12:+}

Et une capture d'écran pour montrer la couleur. Notez que les deux points ne sont PAS colorés ou stylisés pour correspondre au texte environnant à gauche et à droite. Il s'agit d' un comportement intentionnel et conçu pour agir comme un séparateur visuel entre les numéros de ligne ajoutés à gauche et la git diffsortie d' origine à droite.

entrez la description de l'image ici

2/3: Qu'est-ce que c'est?

Du haut degit-diffn.sh :

LA DESCRIPTION:

git-diffn.sh

  1. un remplacement git diffinstantané pour lequel affiche également les numéros de ligne! Utilisez-le exactement comme git diff, sauf que vous verrez également ces magnifiques numéros de ligne pour vous aider à comprendre vos modifications.

  2. puisqu'il s'agit simplement d'un wrapper léger basé sur le langage awk git diff, il accepte TOUTES les options et paramètres qui git diffacceptent. Exemples:

  3. git diffn HEAD~

  4. git diffn HEAD~3..HEAD~2

  5. fonctionne avec tous vos git diffparamètres de couleur, même si vous utilisez des couleurs personnalisées

  6. Voir ma réponse ici pour savoir comment définir des couleurs de diff personnalisées, ainsi que pour voir une capture d'écran de la sortie de couleur personnalisée à partir de git diffn: Comment personnaliser la couleur de l'en-tête de diff dans git diff?

  7. Voici quelques exemples de git configcommandes de ma réponse ci-dessus pour définir des git diffcouleurs et des attributs personnalisés (mise en forme du texte):

       git config --global color.diff.meta "blue"
       git config --global color.diff.old "black red strike"
       git config --global color.diff.new "black green italic"
       git config --global color.diff.context "yellow bold"
    
  8. dans git diffn, la sortie couleur est activée par défaut; si vous souhaitez désactiver la couleur de sortie, vous devez utiliser --no-colorou --color=never. Voir man git diffpour plus de détails. Exemples:

     git diffn --color=never HEAD~
     git diffn --no-color HEAD~3..HEAD~2
    

3/3: Installation

  1. Windows (non testé): cela peut fonctionner dans le terminal bash fourni avec Git pour Windows , mais n'est pas testé. Installez Git pour Windows. Ouvrez le terminal bash fourni avec et essayez de suivre les instructions ci-dessous. J'ai besoin de quelques testeurs qui vont tester cela dans Git pour Windows. Veuillez consulter et répondre ici: https://github.com/git-for-windows/git/issues/2635 .
  2. Mac (non testé): utilisez le terminal et suivez les instructions ci-dessous. Vous devrez peut-être installer gawk. Si oui, essayez ce : brew install gawk.
  3. Linux (testé sur Ubuntu 18.04 et fonctionne parfaitement): suivez les instructions du terminal ci-dessous.

Option 1 (ma recommandation): téléchargez tout le dépôt, puis créez un lien symbolique vers le programme afin que vous puissiez facilement recevoir des mises à jour en effectuant une git pulldepuis le dépôt quand vous le souhaitez.

Tout d'abord, cdà l'endroit où vous souhaitez l'installer. Puis exécutez:

git clone https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles.git
cd eRCaGuy_dotfiles/useful_scripts
mkdir -p ~/bin
ln -si "${PWD}/git-diffn.sh" ~/bin/git-diffn

Terminé! Maintenant, faites simplement la dernière étape ci-dessous!

Option 2 (pour ceux qui veulent juste le fichier 1): ne téléchargez qu'un seul fichier une fois.

mkdir -p ~/bin
cd ~/bin
wget https://raw.githubusercontent.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles/master/useful_scripts/git-diffn.sh
chmod +x git-diffn.sh
mv git-diffn.sh git-diffn

Terminé! Maintenant, faites simplement la dernière étape ci-dessous!

Dernière étape:

Maintenant, fermez et rouvrez votre terminal, ou re-sourcez-le avec . ~/.bashrc, et vous avez terminé!

git diffnfonctionnera désormais comme un remplacement exact pour git diff!

Gabriel Staples
la source
1

Tu peux essayer

git blame

sur le fichier. Il vous montre le validateur, l'identifiant de validation et le numéro de ligne pour chaque ligne du fichier.

Juan
la source
4
Le problème avec cela est qu'il ne vous montre pas de différence , ce que l'affiche originale a demandé. git blameaffichera simplement l'état actuel du fichier avec les numéros de ligne.
5
Je savais pour git blame, mais quelqu'un sur Google pourrait ne pas avoir. Cela pourrait aider quelqu'un. Merci de répondre.
Drew LeSueur
git blamene répond en aucun cas à la question; Je suis assez déconcerté par les votes positifs ici
Michael Mrozek
Veuillez ne pas spammer le stackoverflow avec des réponses qui ne sont pas liées aux questions.
Ahmed
0

Tout d'abord, configurez votre outil git diff, par exemple Meld

git config --global diff.tool meld

Ensuite, tirez votre difftool sur un fichier:

git difftool -y config.rb

N'oubliez pas de définir le numéro de ligne dans les préférences de votre outil de comparaison.

HaxtraZ
la source