Используя git diff, как я могу получить добавленные и измененные номера строк? - PullRequest
69 голосов
/ 24 ноября 2011

Предположим, у меня есть текстовый файл

alex
bob
matrix
will be removed
git repo

, и я обновил его до

alex
new line here
another new line
bob
matrix
git

Здесь я добавил номер строки (2,3) и обновленный номер строки(6)

Как получить информацию об этих номерах строк, используя git diff или любую другую команду git?

Ответы [ 10 ]

62 голосов
/ 24 ноября 2011

git diff --stat покажет вам результат, который вы получаете при совершении вещи, о которой вы, я полагаю, говорите.

git diff --stat

Для точного отображения номеров строк, которые вы изменили, вы можете использовать

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

И измененная строка будет последним числом перед конечной скобкой в ​​результате. Не чистое решение, хотя: (

27 голосов
/ 29 августа 2012

Вот функция bash для вычисления результирующих номеров строк из 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
}

Может выдавать такие данные как:

$ 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);

из различий вроде этого:

$ 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);

Если вы хотите показать только добавленные / удаленные / измененные строки, а не окружающий контекст, вы можете передать -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);

Он устойчив к цветовым кодам ANSI, поэтому вы можете передать --color=always в git diff, чтобы получить обычное цветовое кодирование для добавленных / удаленных линий.

Вывод можно легко найти:

$ 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);

В вашем случае git diff -U0 даст:

$ 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

Если вам нужны номера строк, измените echo "$path:$line:$REPLY" на echo "$line" и направьте вывод через uniq.

16 голосов
/ 18 июля 2014

Я использую --unified=0 вариант git diff.

Например, git diff --unified=0 commit1 commit2 выводит разность:

*enter image description here*

Из-за *Опция 1011 *, вывод diff показывает 0 строк контекста;другими словами, он показывает точно измененные строки .

Теперь вы можете определить строки, начинающиеся с '@@', и проанализировать их на основе шаблона:

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

Возвращаясь к приведенному выше примеру, для файла WildcardBinding.java, начиная со строки 910, удаляются 0 строк.Начните со строки 911, добавьте 4 строки.

6 голосов
/ 20 мая 2014

У меня была такая же проблема, поэтому я написал скрипт gawk, который изменяет вывод git diff, добавляя номер строки для каждой строки.Иногда я нахожу это полезным, когда мне нужно различить рабочее дерево, хотя это не ограничивается этим.Может быть, кому-то это пригодится?

$ 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

Вы можете скачать его здесь:
https://github.com/jay/showlinenum

3 голосов
/ 25 февраля 2016

Номера строк всех незафиксированных строк (добавлены / изменены):

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

Пример вывода:

1
2
8
12
13
14
2 голосов
/ 24 ноября 2011

Настройте внешний инструмент сравнения, который покажет вам номера строк. Например, это то, что у меня есть в моей глобальной конфигурации 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"

См. Этот ответ для более подробной информации: https://stackoverflow.com/q/949242/526535

1 голос
/ 01 декабря 2013

Вы можете использовать git diff в сочетании с параметром shortstat, чтобы просто показать измененные строки no из .

Для количества строк, измененных (в файле, который уже находится в репо) с момента вашей последней фиксации

git diff HEAD --shortstat

Будет выведено что-то похожее на

1 file changed, 4 insertions(+)
1 голос
/ 30 ноября 2012

Вот функция bash, которую я собрал вместе:

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

И в конечном итоге это выглядит так:

views.py:
403,404,533-538,546-548,550-552,554-559,565-567,580-582
0 голосов
/ 26 июня 2014

Вероятно, это довольно точное количество измененных строк:

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

Кроме того, вот решение для номеров строк в вашем diff: https://github.com/jay/showlinenum

0 голосов
/ 24 ноября 2011

Не совсем то, что вы просили, но git blame TEXTFILE может помочь.

...