Git的diff输出中,"@@ -1 +1 @@"是什么意思?

130

我一直在收集从信息返回的数据

git diff <commitId>..<commitId>

我遇到了 @@ -1 +1 @@

我没能理解那是什么意思。我在谷歌上搜索了一些内容,但没有结果。


你能描述一下哪个文件会产生这样的头部吗? - kworr
@kworr 这有点儿愚蠢的问题,任何统一格式的差异都有范围头。 - Yuval Adam
@YuvalAdam:实际上,diff统一格式有更多需要填写的字段,比如[-+]<位置>,<行数>,而在这里我们没有显示任何更改,但是这些更改涉及文件的第一行。 - kworr
3个回答

101

简单示例分析

格式基本上与 diff -u 统一的差异一致。

例如考虑以下情况:

diff -u <(seq -w 16) <(seq -w 16 | grep -Ev '^(02|03|14|15)$')

其中:

  • 第一个文件包含010216
  • 第二个文件也包含相同的内容,但删除了行02031415

差异输出:

@@ -1,6 +1,4 @@
 01
-02
-03
 04
 05
 06
@@ -11,6 +9,4 @@
 11
 12
 13
-14
-15
 16

@@ -1,6 +1,4 @@ 的意思是:

  • -1,6表示第一份文件的这部分从第1行开始,总共显示6行。因此它显示了1到6行。

    1
    2
    3
    4
    5
    6
    

    -表示“旧”,因为我们通常将其称为diff -u old new

  • +1,4表示第二份文件的这部分从第1行开始,总共显示4行。因此它显示了1到4行。

    +表示“新”。

    我们只有4行而不是6行,因为删除了2行! 新的块就是:

    01
    04
    05
    06
    

@@ -11,6 +9,4 @@ 第二个块的类比如下:

  • 在旧文件中,我们有6行,从旧文件的第11行开始:

    11
    12
    13
    14
    15
    16
    
  • 在新文件中,我们有4行,从新文件的第9行开始:

    11
    12
    13
    16
    

    请注意,因为我们已经在之前的块中删除了2行(2和3),所以第11行是新文件的第9行。

代码块头

根据您的 Git 版本和配置,您还可以在 @@ 行旁边得到一行代码,例如以下示例中的 func1() {

@@ -4,7 +4,6 @@ func1() {

这也可以通过纯文本 diff-p 标志获得。

例如:旧文件:

func1() {
    1;
    2;
    3;
    4;
    5;
    6;
    7;
    8;
    9;
}

如果我们移除第6行,差异将显示为:
@@ -4,7 +4,6 @@ func1() {
     3;
     4;
     5;
-    6;
     7;
     8;
     9;

请注意这不是func1的正确行:它跳过了第12行。

这个很棒的功能经常告诉我们每个代码块属于哪个函数或类,这对于解释差异非常有用。

如何选择头文件的算法确切地讨论在这里:Git差异块头摘录来自哪里?

一行简略表示法

这种情况非常少见,但请考虑:

diff -U0 <(seq -w 16) <(seq -w 16 | sed 's/10/hack/')

其中:

  • -U0:使用 0 行上下文
  • 第二个文件将 10 替换为 hack

在这种情况下,差异输出如下:

@@ -10 +10 @@
-10
+hack

我们知道,当出现单行更改时,标记会被总结为只显示一个数字而不是 m,n 对。

这种行为在Todd's answer引用的文档中有所记录:

如果一个块只包含一行,则只显示其起始行号。否则,它的行号看起来像是起始行号、计数。空白的块被认为从后续块之后的行开始。

单行块添加和删除的样子如下,删除:

diff -U0  <(seq -w 16) <(seq -w 16 | grep -Ev '^(10)$')

输出:

@@ -10 +9,0 @@
-10

添加:

$ diff -U0 <(seq -w 16 | grep -Ev '^(10)$') <(seq -w 16)

输出:

@@ -9,0 +10 @@
+10

已在diff 3.8和Ubuntu 22.10上进行测试。


1
啊,所以我会把 @@ -1,6 +1,4 @@ 读作:“从第1行开始,旧的行数为6,但新的行数为4”。 - Cloud
1
@Cloud 对的,就是这样 :-) - Ciro Santilli OurBigBook.com
这个问题涉及到单行代码块的行数省略,而本答案并未解决此问题。 - fuzzyTew
1
@fuzzyTew 现在可以了 - Ciro Santilli OurBigBook.com

77
这是一个统一的diff块标识符。这个东西由GNU Diffutils记录文档。
统一的输出格式以两行标题开头,如下所示:
--- 源文件 源文件修改时间
+++ 目标文件 目标文件修改时间
时间戳看起来像2002-02-21 23:30:39.942229878 -0800,用于表示日期、带分数秒的时间和时区。不支持分数时间戳的主机将省略分数秒。
你可以使用--label=label选项更改标题内容,可以参考替代名称
接下来是一个或多个差异块;每个块都显示了文件之间的一个差异区域。统一格式的差异块如下所示:
@@ 源文件行号 目标文件行号 @@
 来自任意文件的行
 来自任意文件的行...
如果一个差异块只包含一行,则仅显示其起始行号。否则,它的行号看起来像起始数量。一个空白块被认为从块后面的行开始。
如果一个差异块和它的上下文包含两个或多个行,则它的行号看起来像起始数量。否则,仅显示其结束行号。一个空白块被认为在块之前的行结束。
两个文件中共同的行以空格字符开头。实际上不同的行在左侧打印列中具有以下指示符字符:
  • +
    第一个文件中添加了一行。
  • -
    第一个文件中删除了一行。

7

1
谢谢。帮了个忙。当没有尾随逗号和s时,默认为1。 - SSEMember

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接