Git diff с номерами строк (журнал Git с номерами строк)


93

Когда я выполняю a git diffили a git log -p, как мне получить номера строк исходного файла (ов), встроенные в вывод?

Я попытался найти это, man git-diff | grep "line numbers"и я попытался погуглить, но ничего быстро не нашел.

Ответы:


92

Вы не можете получить удобочитаемые номера строк с помощью git diff

В настоящее время нет никаких опций, чтобы номера строк отображались вертикально сбоку git diff.

Формат унифицированного сравнения

Эта информация доступна в заголовках блоков (c) для каждого изменения в diff, хотя она просто в формате unified-diff :

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

Исходное состояние файла представлено с помощью -, а новое состояние представлено с помощью +(они не означают добавления и удаления в заголовке startблока . Представляет собой начальный номер строки каждой версии файла и countпредставляет, сколько строк включено , начиная с начальной точки.

пример

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

Заголовок фрагмента

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

говорит, что предыдущая версия файла начинается со строки 11 и включает 7 строк:

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

а следующая версия файла также начинается со строки 11 и также включает 7 строк.

Формат Unified-diff не предназначен для использования людьми

Как вы, наверное, догадались, формат unified-diff не позволяет легко вычислить номера строк (по крайней мере, если вы не компьютер). Если вам действительно нужны номера строк, которые вы можете прочитать, вам понадобится инструмент сравнения, который отобразит их для вас.

Дополнительное чтение


4
Вот команда grep для извлечения только номеров строк в измененных файлах, например, для использования для фильтрации отчета в стиле проверкиgit diff --unified=0 | grep -Po '^\+\+\+ ./\K.*|^@@ -[0-9]+(,[0-9]+)? \+\K[0-9]+(,[0-9]+)?(?= @@)'
Якуб Боченски

1
Комментарий @ JakubBochenski довольно хорошо решил мою проблему.
0xbe5077ed

Это действительно полезно, только если вы укажете --unified=0или -U0.
каркать

Я только что закончил git diffnзамену (оболочку), для git diffкоторой показаны номера строк и полная совместимость со всеми вариантами использования и опциями git diff: stackoverflow.com/questions/24455377/…
Габриэль Скобы,

22

Вот еще два решения, расширяющие код Энди Тальковски.

Простой текст:

  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}'

Цветной текст при условии, что \033[66mэто формат цветовых кодов:

  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}'

Код изменяет строки , которые начинаются с -и +к -1:-и +1:+, соответственно, и линии , которые начинаются с чем к (5,6):. Цифры - это номера строк из соответствующего файла.


Я заметил, что это нарушает выравнивание (отступы) кода, тогда как native git diffтщательно поддерживает выравнивание. Этот код сейчас не у меня в голове, не могли бы вы его исправить? Другими словами, когда в одной строке говорится, +240:+а в следующей - (241,257):, вам нужно добавить несколько дополнительных пробелов в верхнюю строку, чтобы ее код поддерживал правильное выравнивание и отступ с кодом из нижней строки. Может быть, это легко сделать с помощью печати?
Габриэль Стейплс

... Я имею в виду с printf.
Габриэль Стейплс


Ничего; Я понял! Я только что закончил git diffn. Смотрите здесь: stackoverflow.com/a/61997003/4561887 . Спасибо @PFudd за ваш ответ. Я изучил его и использовал для изучения, затем начал с нуля и написал git diffn. После форматирования, чтобы я мог прочитать ваш код (спасибо @EdMorton), я смог извлечь из него несколько замечательных вещей, которые мне помогли.
Габриэль Стейплс

6

Вот сценарий, который пытается исправить это - не тестировал его в гневе, но вроде нормально. Он полагается на записи, которые производит git diff, и использует awk для подсчета строк.

# 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 

4

Вы можете использовать git difftoolдля сравнения с внешним редактором, который будет отображать номера строк. Вот как это сделать с помощью vim / vimdiff:

  1. Установите vimdiff как инструмент git difftool:

    git config --global diff.tool vimdiff
    
  2. Настройте ~/.vimrcавтоматическое отображение номеров строк при использовании vimdiff:

    if &diff
        set number
    endif
    
  3. Запустите git difftool, который будет использовать vimdiff с номерами строк:

    git difftool
    

Выполнив только git difftool, я открыл для меня инструмент tkdiff, который сам имеет функцию номера строки. Благодаря wisbucky
Richardd

3

Быстрый способ - использовать git diff -U0. Это установит строки контекста в 0, что приведет к совпадению значений @@ с фактическими измененными строками. По умолчанию значения @@ включают 3 строки контекста до / после, что неудобно для людей.

Пример:

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

Трудно вычислить номера строк измененных строк, потому что строка 10 относится к первой строке предыдущего контекста. Фактический номер первой измененной строки - 10 + 3 = 13. Чтобы рассчитать количество измененных строк, вам также нужно вычесть контекст до и после: 8-3-3 = 2.

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

Как видите, установка context = 0 упрощает чтение значений @@ для людей. Вы можете видеть, что измененные строки начинаются со строки 13, и есть 2 измененные строки.

Это не идеально, поскольку показывает только номер строки для каждого блока. Если вы хотите видеть номера строк для каждой строки, используйте difftool для внешнего редактора. См. Https://stackoverflow.com/a/50049752


3

Я хотел бы использовать git difftoolс Meld как мой difftool. На него легче смотреть git diff, он имеет красивое параллельное сравнение графического интерфейса и показывает номера строк с каждой стороны.

Настроить:

  1. Инструкции по настройке meld в качестве инструментария различий для Windows или Linux

Пример снимка экрана:

введите описание изображения здесь

Обновление 24 мая 2020 г .:

Я только что написал git diffnза последние несколько дней, чтобы заменить его git diffв командной строке. Дать ему шанс. Смотрите мой другой ответ здесь .


3

С 24 мая 2020 года вы теперь можете использовать сторонний инструмент git diffn(полное раскрытие: я написал его) для этой цели. Это легкая оболочка git diff, написанная на awkязыке программирования, основанном на шаблонах / действиях. Вот пример вывода из работы git diffn:

введите описание изображения здесь

1/3: Что это такое?

Из верхней частиgit-diffn.sh :

ОПИСАНИЕ:

git-diffn.sh

  1. замена, для git diffкоторой также отображаются номера строк! Используйте его точно так же git diff, за исключением того, что вы также увидите эти красивые номера строк, которые помогут вам понять свои изменения.

  2. поскольку это всего лишь легкая оболочка на основе языка awk git diff, она принимает ВСЕ принимаемые параметры и параметры git diff. Примеры:

  3. git diffn HEAD~

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

  5. работает с любыми git diffнастройками цвета, даже если вы используете собственные цвета

  6. См. Мой ответ здесь, чтобы узнать, как установить пользовательские цвета различий, а также увидеть снимок экрана с выводом нестандартных цветов из git diffn: Как настроить цвет заголовка diff в git diff?

  7. Вот несколько примеров git configкоманд из моего ответа выше для установки пользовательских git diffцветов и атрибутов (форматирование текста):

       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. in git diffnпо умолчанию цветной вывод включен; если вы хотите отключить выходной цвет, вы должны использовать --no-colorили --color=never. Подробнее man git diffсм. Примеры:

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

2/3: Установка

  1. Windows (не проверено): это может работать внутри терминала bash, который поставляется с Git для Windows , но не проверено. Установите Git для Windows. Откройте терминал bash, с которым он поставляется, и попробуйте следовать приведенным ниже инструкциям. Мне нужны тестировщики, которые протестируют это в Git для Windows. См. И ответьте здесь: https://github.com/git-for-windows/git/issues/2635 .
  2. Mac (непроверенный): используйте терминал и следуйте инструкциям ниже. Возможно, вам потребуется установить gawk. Если это так, попробуйте это : brew install gawk.
  3. Linux (протестирован на Ubuntu 18.04 и отлично работает): следуйте инструкциям терминала ниже.

Вариант 1 (моя рекомендация): загрузите все репо, а затем создайте символическую ссылку на программу, чтобы вы могли легко получать обновления, выполняя git pullиз репозитория в любое время.

Во-первых, cdтуда, куда вы хотите это установить. Затем запустите:

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

Выполнено! Теперь просто сделайте последний шаг ниже!

Вариант 2 (для тех, кому нужен только 1 файл): загрузите только один файл один раз.

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

Выполнено! Теперь просто сделайте последний шаг ниже!

Последний шаг:

Теперь закройте и снова откройте свой терминал или повторно используйте его . ~/.bashrc, и все готово!

git diffnтеперь будет работать как точная замена для git diff!

Вот демо:

3/3: Демо git diffn:

Создайте этот файл:

hello_world.c:

#include <stdio.h>

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

    return 0;
}

Зафиксируйте это:

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

Измените его на это и сохраните файл:

hello_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;
}

Теперь запустите:

git diff

Вот результат git difffirst для сравнения:

$ 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
+}

И скриншот, чтобы показать цвет. Обратите внимание, что выделенный красным раздел просто показывает пустые пробелы (в данном случае пробелы), которые можно удалить:

введите описание изображения здесь

Теперь вот результат git diffn. Обратите внимание, что он отлично показывает все номера строк!

  • Номера строк для удаленных строк указаны слева и показывают -знак как в крайнем левом, так и в правом углу, :чтобы помочь вам лучше видеть - независимо от того, любят ли ваши глаза сканировать вниз вправо от двоеточия или вниз в дальнем слева от экрана.
  • Номера строк для добавленных строк находятся дальше вправо и показывают +знак как крайний левый, так и справа от :.
  • Номера строк для неизмененных строк, показанных для контекста, показаны как для левого (старый файл), так и для правого (новый файл), разделенные знаком ,.

Выход 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:+}

И скриншот, чтобы показать цвет. Обратите внимание, что двоеточия НЕ окрашены или стилизованы в соответствии с окружающим текстом слева и справа. Это намеренное и разработанное поведение, которое действует как визуальный разделитель между номерами строк, добавленными слева, и исходным git diffвыводом справа.

введите описание изображения здесь


1

Можешь попробовать

git blame

в файле. Он показывает вам коммиттера, идентификатор фиксации и номер строки для каждой строки в файле.


4
Проблема в том, что он не показывает разницу , как того требовал исходный постер. git blameпросто покажет текущее состояние файла с номерами строк.

5
Я знал о git blame, но кто-то погуглил, возможно, не знал. Это может кому-то помочь. Спасибо за ответы.
Drew LeSueur

git blameникоим образом не отвечает на вопрос; Я довольно озадачен голосованием здесь
Майкл

Пожалуйста, не рассылайте в stackoverflow ответы, не относящиеся к вопросам.
Ахмед

0

Сначала настройте инструмент git diff, например Meld

git config --global diff.tool meld

Затем скопируйте свой difftool в какой-нибудь файл:

git difftool -y config.rb

Не забудьте установить номер строки в настройках вашего инструмента сравнения.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.