【问题标题】:Where does the excerpt in the git diff hunk header come from?git diff hunk 标头中的摘录来自哪里?
【发布时间】:2015-03-22 13:24:46
【问题描述】:

当我在 C# 文件上使用 git diff 时,我看到如下内容:

diff --git a/foo.cs b/foo.cs
index ff61664..dd8a3e3 100644
--- a/foo.cs
+++ b/foo.cs
@@ -15,6 +15,7 @@ static void Main(string[] args)
                    string name = Console.ReadLine();
             }
             Console.WriteLine("Hello {0}!", name);
+            Console.WriteLine("Goodbye");
         }
     }
 }

hunk 标题行包含当前方法的第一行 (static void Main(string[] args)),这很棒。但是它似乎不是很可靠...我看到很多情况下它不起作用。

所以我想知道,这段摘录来自哪里? git diff 是否以某种方式识别语言语法?有没有办法自定义?

【问题讨论】:

    标签: git syntax diff


    【解决方案1】:

    有没有办法自定义?

    配置定义在.gitattributes, section "Defining a custom hunk-header":

    首先,在.gitattributes 中,您将为路径分配diff 属性。

    *.tex diff=tex
    

    然后,您将定义一个“diff.tex.xfuncname”配置来指定一个正则表达式,该正则表达式与您希望显示为大块标题“TEXT”的行相匹配。像这样在$GIT_DIR/config 文件(或$HOME/.gitconfig 文件)中添加一个部分:

    [diff "tex"]
       xfuncname = "^(\\\\(sub)*section\\{.*)$"
    

    注意。配置文件解析器会吃掉单级反斜杠,因此您需要将反斜杠加倍;上面的模式选择以反斜杠开头的行,零次或多次出现 sub 后跟 section 后跟左大括号,直到行尾。

    有一些内置的模式可以让这更容易,tex就是其中之一,所以你不必在你的配置文件中写上上面的内容(你仍然需要使用属性机制来启用它,通过.gitattributes)。

    ('csharp' 是当前内置模式的一部分)




    这段摘录来自哪里?
    git diff 是否能以某种方式识别语言语法?

    最初,该算法对于函数名称检测非常粗糙:
    请参阅commit acb7257(Git 1.3.0,2006 年 4 月,作者 Mark Wooding)

    xdiff:在大块头中显示函数名称。

    内置差异生成器的速度不错;但函数名称 diff -p 显示的真的很好。而且我讨厌不得不选择。
    所以,我们破解xdiff 来找到函数名并打印出来。

    函数名是由一个特别愚蠢的算法解析的 时刻:它只是试图在“旧”文件中找到一行,从之前 大块头的开始,他的第一个角色看起来很合理。尽管如此,还是 绝对是一个开始。


    它使用get_func_line() 进行了改进,它本身来自commit f258475(Git 1.5.3,2007 年 9 月,作者 Junio C Hamano (gitster))

    您可以在该提交测试中看到t/t4018-diff-funcname.sh,以测试自定义差异函数名称模式。

    基于每个路径属性的块头选择。

    这使得“diff -p”大块标头可通过gitattributes 机制进行自定义。
    它基于 Johannes 的早期补丁,允许定义单个 正则表达式可用于所有内容。

    到达用于定义块头的正则表达式的机制 与gitattributes的其他用法相同。
    您分配一个属性,funcname(因为“diff -p”通常使用补丁的函数名称作为块头),一个简单的字符串值。
    这可以是内置模式的名称之一(当前定义为java")或自定义模式名称,从配置文件中查找。

     (in .gitattributes)
     *.java   funcname=java
     *.perl   funcname=perl
    
     (in .git/config)
     [funcname]
       java = ... # ugly and complicated regexp to override the built-in one.
       perl = ... # another ugly and complicated regexp to define a new one.
    

    当前的 xfuncname 语法在 commit 45d9414 中引入,Git 1.6.0.3,2008 年 10 月,作者 Brandon Casey

    diff.*.xfuncname 使用“扩展”正则表达式进行大块标头选择

    目前,由“diff -p”生成的大块标头可通过以下方式自定义 在配置文件中设置diff.*.funcname 选项。 'funcname' 选项采用基本的正则表达式。此功能是使用 GNU 正则表达式库设计的,默认情况下,它允许使用一些扩展正则表达式运算符的反斜杠版本,即使在基本正则表达式模式下也是如此。例如,以下字符在使用反斜杠时根据扩展正则表达式规则进行解释:?+|
    因此,内置的funcname 模式是使用一些扩展的 正则表达式运算符。

    其他更严格遵守 POSIX 规范的平台不 解释基本正则表达式中的反斜杠扩展 RE 运算符 模式。这会导致内置 funcname 模式的模式匹配 在这些平台上失败。

    引入一个使用扩展正则表达式的新选项“xfuncname”,并宣传它而不是funcname
    由于大多数用户都在 GNU 平台上,因此大多数 funcname 模式都是在那里创建和测试的。
    只做广告xfuncname 应该有助于避免创建可用于 GNU 正则表达式但不适用于其他地方的不可移植模式。

    此外,扩展的正则表达式可能不那么难看,而且 与基本 RE 相比复杂,因为许多常见的特殊运算符不需要反斜杠。

    例如,GNU Basic RE:

    ^[    ]*\\(\\(public\\|static\\).*\\)$
    

    成为以下扩展 RE:

    ^[    ]*((public|static).*)$
    

    最后,它已扩展为 commit 14937c2,用于 git 1.7.8(2011 年 12 月),由 René Scharfe 撰写。

    diff:添加选项以将整个函数显示为上下文

    将选项-W/--function-context 添加到git diff
    它类似于git grep 的相同选项,并扩展了更改块的上下文,以便显示整个周围的功能。
    这种“自然”的背景可以让人们更好地理解变化。


    它仍在 Git 2.15(2017 年第四季度)中进行调整

    检测 HTML 的“函数头”的内置模式确实 不匹配没有任何属性的<H1>..<H6> 元素,它有 已修复。

    在 2.15 之前,它无法匹配 <h1>...</h1>,而 <h1 class="smth">...</h1> 匹配。

    参见Ilya Kantor (iliakan)commit 9c03cac(2017 年 9 月 23 日)。
    (由 Junio C Hamano -- gitster -- 合并于 commit 376a1da,2017 年 9 月 28 日)


    检测函数边界的模式称为xfuncref

    参见 Łukasz Niemier (hauleth)commit a807200(2019 年 11 月 8 日)。
    (由 commit 376e730 中的 Junio C Hamano -- gitster -- 合并,2019 年 12 月 1 日),适用于 Git 2.25(2020 年第一季度)

    userdiff:将 Elixir 添加到支持的用户差异语言中

    签字人:Łukasz Niemier
    签字人:Johannes Sixt

    Elixir 语言中添加了对xfuncref 的支持,这是一种在Erlang 虚拟机(BEAM) 上运行的类Ruby 语言。

    还有:

    参见Ed Maste (emaste)commit d1b1384(2019 年 12 月 13 日)。
    (由 Junio C Hamano -- gitster -- 合并于 commit ba6b662,2019 年 12 月 25 日)

    userdiff:从elixir regex 中删除空子表达式

    签字人:Ed Maste
    审核人:Jeff King
    帮助人:Johannes Sixt

    正则表达式无法在 FreeBSD 上编译。

    还添加/* -- */ 标记以分隔提供给PATTERNS() 宏的两个正则表达式条目,以使其与其他内容类型的模式一致。


    Git 2.27(2020 年第二季度)添加了 Markdown 文档的 userdiff 模式。

    参见Ash Holland (sersorrel)commit 09dad92(2020 年 5 月 2 日)。
    (由 Junio C Hamano -- gitster -- 合并到 commit dc4c393,2020 年 5 月 8 日)

    userdiff: 支持 Markdown

    签字人:Ash Holland
    签字人:Johannes Sixt

    通常会在源代码旁边找到 Markdown 文档,并且为文档更改提供更好的上下文很有用;另见commit 69f9c87d4(“userdiff:添加对 Fountain 文档的支持”,2015-07-21,Git v2.6.0-rc0 -- merge 列在batch #1)。

    该模式基于 CommonMark specification 0.29, section 4.2 https://spec.commonmark.org/ 但不匹配空标题,因为在大标题中看到它们不太可能有用。

    仅支持 ATX 标题,因为检测 setext 标题需要在模式匹配或匹配多行模式之前打印行。 word-diff 模式与 HTML 的模式相同,因为许多 Markdown 解析器都接受内联 HTML。


    在 Git 2.30(2021 年第一季度)中,userdiff 模式学会了识别 POSIX shell 和 bash 中的函数定义。

    参见Victor Engmark (l0b0)commit 2ff6c34(2020 年 10 月 22 日)。
    (由 Junio C Hamano -- gitster -- 合并于 commit 292e53f,2020 年 11 月 2 日)

    userdiff: 支持 Bash

    签字人:Victor Engmark
    签字人:Johannes Sixt

    支持 POSIX、bashism 和混合函数声明、所有四种复合命令类型、尾随 cmets 和混合空格。

    尽管 Bash 允许 locale-dependent characters in function names,但为简单起见,仅检测具有 POSIX.1-2017 允许的字符的函数名称。
    这应该涵盖绝大多数用例,并产生与系统无关的结果。

    由于必须指定单词模式,但没有简单的方法知道默认的单词模式,所以使用默认的IFS 字符作为开始。以后的补丁可以改善这一点。

    gitattributes 现在包含在其man page 中:

    • bash 适用于 Bourne-Again SHell 语言的源代码。
      涵盖 POSIX shell 函数定义的超集。

    在 Git 2.32(2021 年第二季度)中,添加了“Scheme”的用户差异模式。

    参见 Atharva Raykar (tfidfwastaken)commit a437390(2021 年 4 月 8 日)。
    (由 Junio C Hamano -- gitster -- 合并到 commit 6d7a62d,2021 年 4 月 20 日)

    userdiff: 添加对 Scheme 的支持

    签字人:Atharva Raykar

    为类似 Scheme 的语言添加一个差异驱动程序,可识别顶级和本地 define 表单,无论是函数定义、绑定、语法定义还是用户定义的 define-xyzzy 表单。

    还支持 R6RS library 表单、module 表单以及 Racket(PLT 方案)中使用的类和结构声明。

    还支持替代“def”语法,例如 Gerbil Scheme 中的语法,例如 defstruct、defsyntax 等。

    为大块头选择define 形式的基本原理是因为它通常是定义程序结​​构的唯一重要形式,并且计划者使用本地函数定义来隐藏它们的可见性是一种常见模式,因此,感兴趣的不仅是顶级 define
    Schemers 还使用宏扩展语言以提供自己的定义形式(例如,define-test-suite 之类的东西),这也被捕获在 hunk 标头中。

    由于使用module+class* 等形式的变体扩展语法是一种常见做法,因此也支持这些形式。

    单词正则表达式是尽最大努力符合R7RS(第 2.1 节)有效的标识符、符号和数字。

    gitattributes 现在包含在其man page 中:

    • scheme 适用于 Scheme 语言的源代码。

    在 Git 2.33(2021 年第三季度)中,C# 的 userdiff 模式学习了令牌“record”。

    参见 Julian Verdurmen (304NotModified)commit c4e3178(2021 年 3 月 2 日)。
    (由 Junio C Hamano -- gitster -- 合并于 commit f741069,2021 年 7 月 8 日)

    userdiff: 添加对 C# 记录类型的支持

    签字人:Julian Verdurmen
    审核人:Johannes Schindelin

    在 C# 9 中添加记录

    代码示例:

    public record Person(string FirstName, string LastName);
    

    欲了解更多信息,请参阅https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-9


    在 Git 2.34(2021 年第四季度)中,“java”语言的 userdiff 模式已更新。

    参见Tassilo Horn (tsdh)commit a8cbc89(2021 年 8 月 11 日)。
    (由 Junio C Hamano -- gitster -- 合并于 commit a896086,2021 年 8 月 30 日)

    userdiff: 改进 java hunk header 正则表达式

    签字人:Tassilo Horn

    目前,git diff(man) hunk 标头会显示错误的方法签名,如果该方法具有限定返回类型、数组返回类型或泛型返回类型,因为正则表达式不允许在返回类型中使用点 (.)[]<>
    此外,类型参数声明无法匹配。

    添加几个 t4018 测试,为不同的情况断言正确的块头:

    • 枚举常量变化
    • 使用有界类型参数更改泛型方法
    • 使用通配符更改泛型方法
    • 嵌套类中的字段更改

    而且,仍然使用 Git 2.34(2021 年第四季度),C++ 语言的用户差异模式已经更新。

    参见commit 386076e(2021 年 10 月 24 日)、commit c4fdba3commit 637b80ccommit bfaaf19(2021 年 10 月 10 日)和commit 350b87ccommit 3e063decommit 1cf9384(2021 年 10 月 8 日)@987654 @.
    (由 Junio C Hamano -- gitster -- 合并于 commit f3f157f,2021 年 10 月 25 日)

    例如:

    userdiff-cpp: 允许数字中的数字分隔单引号

    签字人:Johannes Sixt

    从C++17开始,单引号可以用作数字分隔符:

    3.141'592'654
    1'000'000
    0xdead'beaf
    

    让 cpp 驱动程序的单词 regex 知道它,这样数字就不会在单引号处分成单独的标记。

    【讨论】:

    • -W 选项我肯定会使用
    • 内置正则表达式可以在这里找到github.com/git/git/blob/master/userdiff.c
    • @David 太好了,感谢您的链接。它是否在某处说明了它默认使用的内容(没有.gitattributes 文件)?
    • @VonC 您到底是如何跟踪这些长期存在的答案,以便在事情发生变化时更新它们?你有一个很棒的数据库吗?美好的回忆?
    • @matt 只是不时检查日志 (github.com/git/git/commits/master)。然后搜索类似的主题,这往往会引导我找到自己过去的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-09
    • 2011-10-07
    • 1970-01-01
    • 2020-08-04
    • 2016-04-29
    相关资源
    最近更新 更多