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

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

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


person Drew LeSueur    schedule 27.06.2014    source источник


Ответы (9)


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

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

Унифицированный формат различий

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

@@ -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 не позволяет легко вычислить номера строк (по крайней мере, если вы не компьютер). Если вам действительно нужны номера строк, которые вы можете прочитать, вам понадобится инструмент сравнения, который отобразит их для вас.

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

person Community    schedule 27.06.2014
comment
Вот команда grep для извлечения только номеров строк в измененных файлах, например будет использоваться для фильтрации отчета в стиле проверки git diff --unified=0 | grep -Po '^\+\+\+ ./\K.*|^@@ -[0-9]+(,[0-9]+)? \+\K[0-9]+(,[0-9]+)?(?= @@)' - person Jakub Bochenski; 06.07.2018
comment
Комментарий @ JakubBochenski довольно хорошо решил мою проблему. - person 0xbe5077ed; 11.09.2018
comment
Это действительно полезно, только если вы укажете --unified=0 или -U0. - person caw; 08.06.2019
comment
Я только что закончил git diffn, заменяющую оболочку (оболочку) для git diff, которая показывает номера строк и имеет полную совместимость со всем использованием и параметрами git diff: stackoverflow.com/questions/24455377/ - person Gabriel Staples; 25.05.2020
comment
@JakubBochenski, что такое флаг -Po у grep? - person Peiti Li; 20.07.2021

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

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

git diff | gawk '
  match($0,"^@@ -([0-9]+),([0-9]+) [+]([0-9]+),([0-9]+) @@",a){
    left=a[1]
    ll=length(a[2])
    right=a[3]
    rl=length(a[4])
  }
  /^(---|\+\+\+|[^-+ ])/{ print;next }
  { line=substr($0,2) }
  /^[-]/{ printf "-%"ll"s %"rl"s:%s\n",left++,""     ,line;next }
  /^[+]/{ printf "+%"ll"s %"rl"s:%s\n",""    ,right++,line;next }
        { printf " %"ll"s %"rl"s:%s\n",left++,right++,line }
'

Вот пример вывода:

diff --git a/.bashrc b/.bashrc
index b2b6d5f..51e0b8c 100644
--- a/.bashrc
+++ b/.bashrc
@@ -1,8 +1,26 @@
 1  1:#!/bin/bash
-2   :# ~/.bashrc: executed by bash(1) for non-login shells.
-3   :# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
-4   :# for examples
+   2:# 2020-03-06 14:54:25 From R S:
+   3:##export PATH="/usr/local/opt/ed/libexec/gnubin:$PATH"
+   4:#export PATH="/usr/local/opt/findutils/libexec/gnubin:$PATH"
+   5:#export PATH="/usr/local/opt/gnu-indent/libexec/gnubin:$PATH"
+   6:#export PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"
+   7:#export PATH="/usr/local/opt/gnu-tar/libexec/gnubin:$PATH"
+   8:#export PATH="/usr/local/opt/gnu-which/libexec/gnubin:$PATH"
 5  9:
+  10:export PATH="/usr/local/opt/sqlite/bin:$PATH"
+  11:export PATH="/usr/local/opt/file-formula/bin:$PATH"
+  12:export PATH="/usr/local/opt/unzip/bin:$PATH"
+  13:export PATH="/usr/local/opt/openssl/bin:$PATH"
+  14:export PATH="/usr/local/opt/wireshark/bin:$PATH"
+  15:
+  16:
+  17:#export PATH="/usr/local/opt/grep/libexec/gnubin:$PATH"

person PFudd    schedule 21.10.2015
comment
Я заметил, что это нарушает выравнивание (отступы) кода, тогда как "родной" git diff тщательно поддерживает выравнивание. Этот код сейчас не у меня в голове, не могли бы вы его исправить? Другими словами, когда в одной строке написано +240:+, а в следующей строке - (241,257):, вам нужно добавить несколько дополнительных пробелов в верхнюю строку, чтобы ее код поддерживал правильное выравнивание и отступ с кодом из нижней строки. Может быть, это легко сделать с помощью печати? - person Gabriel Staples; 21.05.2020
comment
... То есть с printf. - person Gabriel Staples; 21.05.2020
comment
stackoverflow.com/questions/61932427/ - person Gabriel Staples; 21.05.2020
comment
Неважно; Я понял! Я только что закончил git diffn. См. Здесь: stackoverflow.com/a/61997003/4561887. Спасибо @PFudd за ваш ответ. Я изучил его и использовал для изучения, затем начал с нуля и написал git diffn. После форматирования, чтобы я мог читать ваш код (спасибо @EdMorton), я смог многому научиться из него, что помогло мне. - person Gabriel Staples; 25.05.2020
comment
Извините, прошло 5+ лет с тех пор, как я это написал, сейчас я бы сделал более красивую работу. :-) - person PFudd; 07.03.2021
comment
Понял. Но еще не поздно! Вы можете вернуться даже сейчас и по крайней мере очистить отступы и форматирование кода, не меняя его иначе. - person Gabriel Staples; 07.03.2021
comment
Я изменил его и удалил цветную версию просто потому, что git diff не передает цветовые коды при переходе к другой программе. - person PFudd; 08.03.2021
comment
Это произойдет, если вы используете git diff --color=always. Свою git diffn я писал ручками цветами. Без цветов на git diff гораздо труднее смотреть (а на это уже трудно смотреть - я бы хотел сделать meld-подобную версию командной строки, когда это возможно). - person Gabriel Staples; 09.03.2021
comment
Примечание: для красивого форматирования awk используйте gawk -o- с gawk 5.0.1. См. конец моего вопроса с помощью Эда Мортона. - person Gabriel Staples; 09.03.2021

С 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. в 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 diff первым для сравнения:

$ 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. См. Также другой мой ответ здесь, где я просто рекомендую вместо этого использовать meld в качестве git difftool. Meld - это круто, и я использую его более чем git diffn, хотя я использую и то, и другое. Однако, поскольку сейчас доступен git diffn, я почти никогда не использую git diff, если я не нахожусь на другом компьютере.
person Gabriel Staples    schedule 25.05.2020
comment
сначала попробуйте в Linux: скопировано из браузера, вставлено в vim :new git-diffn.sh, "+gP, :wq, chmod +x git-diffn.sh ... сработало. - person John Meyer; 11.03.2021
comment
Отличная документация, подробная, как и должно быть. - person Timo; 16.06.2021

Вот сценарий, который пытается исправить это - не тестировал его в гневе, но вроде нормально. Он полагается на записи, которые производит 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 
person Andy Talkowski    schedule 16.09.2015

Быстрый способ - использовать 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

person wisbucky    schedule 26.04.2018

Вы можете использовать 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
    
person wisbucky    schedule 26.04.2018
comment
Выполнив только git difftool, он открыл для меня инструмент tkdiff, который сам имеет функцию номера строки. Спасибо wisbucky - person Richardd; 07.01.2020

Мне нравится использовать git difftool с meld в качестве инструмента для сравнения. На него легче смотреть, чем на git diff, он имеет красивое параллельное сравнение графического интерфейса и показывает номера строк с каждой стороны.

Настраивать:

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

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

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

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

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

person Gabriel Staples    schedule 07.05.2018

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

git blame

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

person Juan    schedule 27.06.2014
comment
Проблема в том, что он не показывает вам diff, о чем просил исходный постер. git blame просто покажет текущее состояние файла с номерами строк. - person ; 28.06.2014
comment
Я знал о git blame, но кто-то погуглил, возможно, не знал. Это может кому-то помочь. Спасибо за ответ. - person Drew LeSueur; 30.06.2014
comment
git blame никоим образом не отвечает на вопрос; Я очень сбит с толку голосов здесь - person Michael Mrozek; 08.08.2018
comment
Пожалуйста, не рассылайте в stackoverflow ответы, не связанные с вопросами. - person Ahmed; 19.11.2019

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

git config --global diff.tool meld

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

git difftool -y config.rb

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

person ChrisZZ    schedule 16.05.2020