web-dev-qa-db-fra.com

Avec git diff, comment puis-je obtenir des numéros de lignes ajoutés et modifiés?

En supposant que j'ai un fichier texte

alex
bob
matrix
will be removed
git repo

et j'ai mis à jour pour être

alex
new line here
another new line
bob
matrix
git

Ici, j'ai ajouté le numéro de ligne (2,3) et le numéro de ligne mis à jour (6)

Comment puis-je obtenir ces informations sur les numéros de ligne en utilisant git diff ou toute autre commande git?

65
Mahmoud Khaled

git diff --stat vous montrera le résultat que vous obtenez lorsque vous commettez des éléments qui sont ceux dont vous parlez, je suppose.

git diff --stat

Pour afficher exactement les numéros de ligne modifiés, vous pouvez utiliser

git blame -p <file> | grep "Not Committed Yet"

Et la ligne modifiée sera le dernier numéro avant la dernière parenthèse dans le résultat. Pas une solution propre cependant :(

59
Sedrik

Voici une fonction bash permettant de calculer les numéros de ligne résultants à partir d'un diff:

diff-lines() {
    local path=
    local line=
    while read; do
        esc=$'\033'
        if [[ $REPLY =~ ---\ (a/)?.* ]]; then
            continue
        Elif [[ $REPLY =~ \+\+\+\ (b/)?([^[:blank:]$esc]+).* ]]; then
            path=${BASH_REMATCH[2]}
        Elif [[ $REPLY =~ @@\ -[0-9]+(,[0-9]+)?\ \+([0-9]+)(,[0-9]+)?\ @@.* ]]; then
            line=${BASH_REMATCH[2]}
        Elif [[ $REPLY =~ ^($esc\[[0-9;]+m)*([\ +-]) ]]; then
            echo "$path:$line:$REPLY"
            if [[ ${BASH_REMATCH[2]} != - ]]; then
                ((line++))
            fi
        fi
    done
}

Il peut produire des sorties telles que:

$ git diff | diff-lines
http-fetch.c:1: #include "cache.h"
http-fetch.c:2: #include "walker.h"
http-fetch.c:3: 
http-fetch.c:4:-int cmd_http_fetch(int argc, const char **argv, const char *prefix)
http-fetch.c:4:+int main(int argc, const char **argv)
http-fetch.c:5: {
http-fetch.c:6:+       const char *prefix;
http-fetch.c:7:        struct walker *walker;
http-fetch.c:8:        int commits_on_stdin = 0;
http-fetch.c:9:        int commits;
http-fetch.c:19:        int get_verbosely = 0;
http-fetch.c:20:        int get_recover = 0;
http-fetch.c:21: 
http-fetch.c:22:+       prefix = setup_git_directory();
http-fetch.c:23:+
http-fetch.c:24:        git_config(git_default_config, NULL);
http-fetch.c:25: 
http-fetch.c:26:        while (arg < argc && argv[arg][0] == '-') {
fetch.h:1: #include "config.h"
fetch.h:2: #include "http.h"
fetch.h:3: 
fetch.h:4:-int cmd_http_fetch(int argc, const char **argv, const char *prefix);
fetch.h:4:+int main(int argc, const char **argv);
fetch.h:5: 
fetch.h:6: void start_fetch(const char* uri);
fetch.h:7: bool fetch_succeeded(int status_code);

à partir d'un diff comme ceci:

$ git diff
diff --git a/builtin-http-fetch.c b/http-fetch.c
similarity index 95%
rename from builtin-http-fetch.c
rename to http-fetch.c
index f3e63d7..e8f44ba 100644
--- a/builtin-http-fetch.c
+++ b/http-fetch.c
@@ -1,8 +1,9 @@
 #include "cache.h"
 #include "walker.h"

-int cmd_http_fetch(int argc, const char **argv, const char *prefix)
+int main(int argc, const char **argv)
 {
+       const char *prefix;
        struct walker *walker;
        int commits_on_stdin = 0;
        int commits;
@@ -18,6 +19,8 @@ int cmd_http_fetch(int argc, const char **argv, const char *prefix)
        int get_verbosely = 0;
        int get_recover = 0;

+       prefix = setup_git_directory();
+
        git_config(git_default_config, NULL);

        while (arg < argc && argv[arg][0] == '-') {
diff --git a/fetch.h b/fetch.h
index 5fd3e65..d43e0ca 100644
--- a/fetch.h
+++ b/fetch.h
@@ -1,7 +1,7 @@
 #include "config.h"
 #include "http.h"

-int cmd_http_fetch(int argc, const char **argv, const char *prefix);
+int main(int argc, const char **argv);

 void start_fetch(const char* uri);
 bool fetch_succeeded(int status_code);

Si vous souhaitez uniquement afficher les lignes ajoutées/supprimées/modifiées, et non le contexte environnant, vous pouvez transmettre -U0 à git diff:

$ git diff -U0 | diff-lines
http-fetch.c:4:-int cmd_http_fetch(int argc, const char **argv, const char *prefix)
http-fetch.c:4:+int main(int argc, const char **argv)
http-fetch.c:6:+       const char *prefix;
http-fetch.c:22:+       prefix = setup_git_directory();
http-fetch.c:23:+
fetch.h:4:-int cmd_http_fetch(int argc, const char **argv, const char *prefix);
fetch.h:4:+int main(int argc, const char **argv);

Il est robuste face aux codes de couleur ANSI, vous pouvez donc passer --color=always à git diff pour obtenir le code de couleur habituel des lignes ajoutées/supprimées.

La sortie peut être facilement annotée:

$ git diff -U0 | diff-lines | grep 'main'
http-fetch.c:4:+int main(int argc, const char **argv)
fetch.h:4:+int main(int argc, const char **argv);

Dans votre cas, git diff -U0 donnerait:

$ git diff -U0 | diff-lines
test.txt:2:+new line here
test.txt:3:+another new line
test.txt:6:-will be removed
test.txt:6:-git repo
test.txt:6:+git

Si vous souhaitez uniquement les numéros de ligne, remplacez echo "$path:$line:$REPLY" par echo "$line" et transmettez le résultat par uniq.

26
John Mellor

J'utilise l'option --unified=0 de git diff.

Par exemple, git diff --unified=0 commit1 commit2 renvoie le diff:

*enter image description here*

En raison de l'option --unified=0, la sortie diff affiche 0 ligne de contexte; autrement dit, il montre exactement les lignes modifiées .

Maintenant, vous pouvez identifier les lignes qui commencent par '@@' et les analyser selon le modèle: 

@@ -startline1,count1 +startline2,count2 @@

Retour à l'exemple ci-dessus, pour le fichier WildcardBinding.Java, commencez à la ligne 910, 0 lignes sont supprimées. A partir de la ligne 911, 4 lignes sont ajoutées.

15
Ida

J'ai eu le même problème alors j'ai écrit un script gawk qui modifie la sortie de git diff pour ajouter le numéro de ligne pour chaque ligne. Je trouve cela utile parfois lorsque j'ai besoin de travailler différemment, même si cela ne se limite pas à cela. Peut-être est-ce utile pour quelqu'un ici?

$ git diff HEAD~1 |showlinenum.awk
diff --git a/doc.txt b/doc.txt
index fae6176..6ca8c26 100644
--- a/doc.txt
+++ b/doc.txt
@@ -1,3 +1,3 @@
1: red
2: blue
 :-green
3:+yellow

Vous pouvez le télécharger à partir d'ici:
https://github.com/jay/showlinenum

6
Jay

Numéros de ligne de toutes les lignes non validées (ajoutées/modifiées):

git blame <file> | grep -n '^0\{8\} ' | cut -f1 -d:

Exemple de sortie:

1
2
8
12
13
14
3
Rich

Configurez un outil de diff externe qui vous montrera les numéros de ligne. Par exemple, voici ce que j'ai dans ma configuration globale git:

diff.guitool=kdiff3
difftool.kdiff3.path=c:/Program Files (x86)/KDiff3/kdiff3.exe
difftool.kdiff3.cmd="c:/Program Files (x86)/KDiff3/kdiff3.exe" "$LOCAL" "$REMOTE"

Voir cette réponse pour plus de détails: https://stackoverflow.com/q/949242/526535

2
manojlds

Vous pouvez utiliser git diff associé au paramètre shortstat pour afficher simplement le no de lignes modifiées. 

Pour le nombre de lignes modifiées (dans un fichier déjà dans le référentiel) depuis votre dernier commit 

git diff HEAD --shortstat

Il va sortir quelque chose de similaire à 

1 file changed, 4 insertions(+)
2
shahalpk

Voici une fonction bash que j'ai bricolée:

echo ${f}:
for n in $(git --no-pager blame --line-porcelain $1 |
        awk '/author Not Committed Yet/{if (a && a !~ /author Not Committed Yet/) print a} {a=$0}' |
        awk '{print $3}') ; do
    if (( prev_line > -1 )) ; then
        if (( "$n" > (prev_line + 1) )) ; then
            if (( (prev_line - range_start) > 1 )) ; then
                echo -n "$range_start-$prev_line,"
            else
                echo -n "$range_start,$prev_line,"
            fi
            range_start=$n
        fi
    else
        range_start=$n
    fi
    prev_line=$n
done
if (( "$range_start" != "$prev_line" )) ; then
    echo "$range_start-$prev_line"
else
    echo "$range_start"
fi

Et ça finit par ressembler à ça:

views.py:
403,404,533-538,546-548,550-552,554-559,565-567,580-582
1
forivall

Ceci est probablement un décompte assez précis des lignes modifiées:

git diff --Word-diff <commit> |egrep '(?:\[-)|(?:\{\+)' |wc -l

De plus, voici une solution pour les numéros de ligne dans votre diff: https://github.com/jay/showlinenum

0
Jay Carroll

Ce n'est pas exactement ce que vous demandiez, mais git blame TEXTFILE peut aider.

0
u-punkt