具有行号的Git diff(具有行号的Git日志)


92

当我执行a git diff或a时git log -p,如何获取与输出内联的源文件的行号?

我尝试查找它,man git-diff | grep "line numbers"并尝试使用Google谷歌搜索,但很快就没有结果。

Answers:


90

您无法通过以下方式获得人类可读的行号 git diff

当前没有任何选项可以让垂直显示在侧面的行号git diff

统一差异格式

该信息可在(c)hunk头中找到,以用于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行。

统一差异格式并不真正供人类使用

您可能会说,统一差异格式很难弄清行号(至少在您不是计算机的情况下)。如果您确实希望读取行号,则需要使用差异工具来为您显示它们。

附加阅读


3
这是一个grep,仅提取修改后的文件中的行号,例如,用于过滤git diff --unified=0 | grep -Po '^\+\+\+ ./\K.*|^@@ -[0-9]+(,[0-9]+)? \+\K[0-9]+(,[0-9]+)?(?= @@)'
检查样式

1
@JakubBochenski的评论很好地解决了我的问题。
0xbe5077ed

不过,仅当您指定--unified=0或时-U0,这才真正有用。
caw

我刚说完git diffn,一个简易替换(包装),用于git diff这说明行号,并与所有的用法和选项的完全兼容git diffstackoverflow.com/questions/24455377/...
加布里埃尔斯台普斯

22

这是另外两个解决方案,扩展了Andy Talkowski的代码。

纯文本:

  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
理查德

3

一种快速的方法是使用 git diff -U0。这会将上下文行设置为0,这将使@@值与实际更改的行匹配。默认情况下,@@值包含3行前后上下文,这对人类来说不方便。

例:

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

这很难计算更改后的行的行号,因为第10行引用了before上下文的第一行。第一条更改的行的实际行号是10 + 3 = 13。要计算更改的行数,则还必须减去前后上下文:8-3-3 = 2。

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

如您所见,将context设置为0将使@@值更易于人类阅读。您可以看到更改的行从第13行开始,并且有2条更改的行。

这不是完美的,因为它仅显示每个块的行号。如果要查看每行的行号,请使用difftool作为外部编辑器。参见https://stackoverflow.com/a/50049752



2

截至2020年5月24日,您现在可以使用第三方工具git diffn(完全披露:我编写了此工具)来实现此目的。它是轻量级包装git diff,以awk基于模式/动作的编程语言编写。这是运行的示例输出git diffn

在此处输入图片说明

这是一个演示:

1/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右侧原始输出之间的可视分隔符。

在此处输入图片说明

2/3:这是什么?

顶部git-diffn.sh

描述:

git-diffn.sh

  1. 一个直接替换的替代品,git diff它也显示行号“ n”!使用它究竟git diff,但你会看到这些美丽的行号,以及以帮助您做出的更改感。

  2. 由于它只是基于awk语言的轻量级包装器git diff,因此它接受所有接受的选项和参数git diff。例子:

  3. git diffn HEAD~

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

  5. git diff即使您使用自定义颜色,也可以使用任何颜色设置

  6. 有关如何设置自定义diff颜色的信息,请参见此处的答案,以及来自的自定义颜色输出的屏幕截图git diffn如何在git diff中自定义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,默认情况下颜色输出为ON;如果要禁用输出颜色,则必须使用--no-color--color=never。有关man git diff详细信息,请参见。例子:

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

3/3:安装

  1. Windows(未试用):这可能在Git for Windows随附的bash终端中起作用,但未经测试。安装Windows版Git。打开其随附的bash终端,然后尝试按照以下说明进行操作。我需要一些测试人员将在Windows的Git中对此进行测试。请在此处查看并回答: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


1

你可以试试

git blame

在文件上。它显示了文件中每一行的提交者,提交ID和行号。


4
问题在于它没有显示diff,这就是原始海报所要求的。git blame只会以行号显示文件的当前状态。

5
我知道git怪,但是谷歌搜索可能没有。它可能会帮助某人。谢谢回答。
Drew LeSueur 2014年

git blame绝不回答问题;我对这里的投票感到很困惑
Michael Mrozek

请不要使用与问题无关的答案来垃圾邮件。
艾哈迈德

0

首先,配置您的git diff工具,例如Meld

git config --global diff.tool meld

然后,将difftool拖到某个文件上:

git difftool -y config.rb

记住在差异工具的首选项中设置行号。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.