gitattributes

原文: https://git-scm.com/docs/gitattributes

名称

gitattributes - 定义每个路径的属性

概要

$ GIT_DIR / info / attributes,.gitattributes

描述

gitattributes文件是一个简单的文本文件,它为路径名提供attributes

gitattributes文件中的每一行都是以下形式:

  1. pattern attr1 attr2 ...

也就是说,一个模式后跟一个属性列表,用空格分隔。前导空格和尾随空格被忽略。以开头的行将被忽略。以双引号开头的模式以C风格引用。当模式匹配相关路径时,该行上列出的属性将被赋予路径。

对于给定路径,每个属性可以处于以下状态之一:

  1. Set

该路径具有特殊值“true”的属性;这是通过仅列出属性列表中属性的名称来指定的。

  1. Unset

该路径具有特殊值“false”的属性;这是通过在属性列表中列出前缀为短划线-的属性的名称来指定的。

  1. Set to a value

该路径具有指定字符串值的属性;这是通过列出属性的名称,后跟等号=及其在属性列表中的值来指定的。

  1. Unspecified

没有模式匹配路径,没有任何说明路径是否具有属性,路径的属性被称为未指定。

当多个模式与路径匹配时,后一行会覆盖较早的行。这个覆盖是按属性完成的。

模式匹配路径的规则与.gitignore文件中的规则相同(参见 gitignore [5] ),但有一些例外:

  • 消极的模式被禁止

  • 与目录匹配的模式不会递归地匹配该目录中的路径(因此在属性文件中使用尾部斜杠path/语法是没有意义的;使用path/**代替)

在确定为路径分配了哪些属性时,Git会查询$GIT_DIR/info/attributes文件(具有最高优先级),.gitattributes文件与相关路径位于同一目录中,其父目录最多为工作树的顶层(包含.gitattributes的目录越远离有问题的路径,其优先级越低)。最后考虑全局和系统范围的文件(它们具有最低优先级)。

当工作树中缺少.gitattributes文件时,索引中的路径将用作后退。在检出过程中,使用索引中的.gitattributes,然后将工作树中的文件用作后备。

如果您希望仅影响单个存储库(即,将属性分配给特定于该存储库的一个用户工作流的文件),则应将属性放在$GIT_DIR/info/attributes文件中。应该由版本控制并分发到其他存储库的属性(即,所有用户感兴趣的属性)应该进入.gitattributes文件。应该影响单个用户的所有存储库的属性应该放在由core.attributesFile配置选项指定的文件中(参见 git-config [1] )。其默认值为$ XDG_CONFIG_HOME / git / attributes。如果$ XDG_CONFIG_HOME未设置或为空,则使用$ HOME / .config / git / attributes。系统中所有用户的属性应放在$(prefix)/etc/gitattributes文件中。

有时您需要覆盖Unspecified状态路径的属性设置。这可以通过列出前缀为感叹号!的属性的名称来完成。

影响

通过为路径分配特定属性可以影响Git的某些操作。目前,以下操作是属性感知的。

退房和登记入住

git checkoutgit merge 等命令运行时,这些属性会影响存储库中存储的内容如何复制到工作树文件。它们还会影响Git如何在 git addgit commit 中存储您在存储库中的工作树中准备的内容。

text

此属性启用并控制行尾标准化。对文本文件进行规范化后,其行结尾将在存储库中转换为LF。要控制工作目录中使用的行结束样式,请对单个文件使用eol属性,对所有文本文件使用core.eol配置变量。请注意,将core.autocrlf设置为trueinput会覆盖core.eol(请参阅 git-config [1] 中这些选项的定义)。

  1. Set

在路径上设置text属性可启用行尾标准化,并将路径标记为文本文件。在不猜测内容类型的情况下进行行尾转换。

  1. Unset

取消设置路径上的text属性会告诉Git在签入或结帐时不要尝试任何行尾转换。

  1. Set to string value "auto"

text设置为“auto”时,路径将标记为自动行结束转换。如果Git决定内容是文本,则其行结尾将在签入时转换为LF。使用CRLF提交文件时,不会进行任何转换。

  1. Unspecified

如果未指定text属性,Git使用core.autocrlf配置变量来确定是否应转换文件。

任何其他值都会导致Git表现为好像没有指定text

eol

此属性设置要在工作目录中使用的特定行结束样式。它可以在没有任何内容检查的情况下实现行尾转换,从而有效地设置text属性。请注意,在具有CRLF行结尾的索引中的路径上设置此属性可能会使路径被视为脏。再次将索引添加到索引将规范化索引中的行结尾。

  1. Set to string value "crlf"

此设置强制Git在签入时规范化此文件的行结尾,并在签出文件时将它们转换为CRLF。

  1. Set to string value "lf"

此设置强制Git在签入时将行结尾标准化为LF,并在签出文件时阻止转换为CRLF。

向后兼容crlf属性

为了向后兼容,crlf属性解释如下:

  1. crlf text
  2. -crlf -text
  3. crlf=input eol=lf

行尾转换

虽然Git通常单独保留文件内容,但可以将其配置为将行结尾标准化为存储库中的LF,并且可选地,在检出文件时将它们转换为CRLF。

如果您只想在工作目录中使用CRLF行结尾,而不管您正在使用哪个存储库,则可以设置配置变量“core.autocrlf”而不使用任何属性。

  1. [core]
  2. autocrlf = true

这不会强制文本文件的规范化,但确保引入存储库的文本文件在添加时将其行结尾标准化为LF,并且已在存储库中标准化的文件保持规范化。

如果要确保任何贡献者引入存储库的文本文件的行结束标准化,可以将所有文件的text属性设置为“auto”。

  1. * text=auto

这些属性允许细粒度控制,如何转换行结尾。下面是一个示例,它将使Git规范化.txt,.vcproj和.sh文件,确保.vcproj文件的CRLF和.sh文件在工作目录中具有LF,并防止.jpg文件无论其内容如何都被规范化。

  1. * text=auto
  2. *.txt text
  3. *.vcproj text eol=crlf
  4. *.sh text eol=lf
  5. *.jpg -text

| 注意 | 使用推送和拉到中央存储库的跨平台项目中启用text=auto转换时,应对包含CRLF的文本文件进行规范化。 |

从干净的工作目录:

  1. $ echo "* text=auto" >.gitattributes
  2. $ git add --renormalize .
  3. $ git status # Show files that will be normalized
  4. $ git commit -m "Introduce end-of-line normalization"

如果任何不应归一化的文件出现在 git status 中,请在运行 git add -u 之前取消设置text属性。

  1. manual.pdf -text

相反,Git未检测到的文本文件可以手动启用规范化。

  1. weirdchars.txt text

如果core.safecrlf设置为“true”或“warn”,Git将验证当前设置core.autocrlf的转换是否可逆。对于“真实”,Git拒绝不可逆转的转换;对于“警告”,Git仅打印警告但接受不可逆转的转换。安全触发器可以防止对工作树中的文件进行此类转换,但也有一些例外情况。即使……

  • git add 本身不会触及工作树中的文件,下次检出就会,所以安全触发器;

  • git apply 用补丁更新文本文件确实触摸了工作树中的文件,但操作是关于文本文件而CRLF转换是关于修复行结尾不一致的,所以安全性不会触发;

  • git diff 本身不会触及工作树中的文件,它经常运行以检查你打算下一步的更改 git add 。为了及早发现潜在问题,安全触发。

working-tree-encoding

Git将以ASCII或其中一个超集(例如UTF-8,ISO-8859-1,…)编码的文件识别为文本文件。以某些其他编码(例如UTF-16)编码的文件被解释为二进制文件,因此内置的Git文本处理工具(例如 git diff )以及大多数Git web前端都无法显示内容默认情况下这些文件。

在这些情况下,您可以使用working-tree-encoding属性告诉Git工作目录中文件的编码。如果将具有此属性的文件添加到Git,则Git会将指定编码的内容重新编码为UTF-8。最后,Git将UTF-8编码内容存储在其内部数据结构中(称为“索引”)。在结帐时,内容将重新编码回指定的编码。

请注意,使用working-tree-encoding属性可能会有一些陷阱:

  • 替代Git实现(例如JGit或libgit2)和较旧的Git版本(截至2018年3月)不支持working-tree-encoding属性。如果决定使用存储库中的working-tree-encoding属性,则强烈建议确保使用存储库的所有客户端都支持它。

    例如,Microsoft Visual Studio资源文件(*.rc)或PowerShell脚本文件(*.ps1)有时以UTF-16编码。如果将*.ps1声明为UTF-16文件并添加foo.ps1并启用working-tree-encoding Git客户端,则foo.ps1将在内部存储为UTF-8。没有working-tree-encoding支持的客户端将foo.ps1签出为UTF-8编码文件。这通常会给该文件的用户带来麻烦。

    如果不支持working-tree-encoding属性的Git客户端添加新文件bar.ps1,则bar.ps1将在内部“按原样”存储(在此示例中可能为UTF-16)。具有working-tree-encoding支持的客户端将内部内容解释为UTF-8并尝试在检出时将其转换为UTF-16。该操作将失败并导致错误。

  • 将内容重新编码为非UTF编码可能会导致错误,因为转换可能不是UTF-8往返安全。如果您怀疑您的编码不是往返安全,那么将其添加到core.checkRoundtripEncoding以使Git检查往返编码(参见 git-config [1] )。已知SHIFT-JIS(日语字符集)具有UTF-8的往返问题,默认情况下会进行检查。

  • 重新编码内容需要可能减慢某些Git操作的资源(例如 git checkoutgit add )。

仅当您无法以UTF-8编码存储文件并且希望Git能够将内容作为文本处理时,才使用working-tree-encoding属性。

例如,如果您的 * .ps1 文件是带字节顺序标记(BOM)的UTF-16编码,并且您希望Git根据您的平台执行自动行结束转换,请使用以下属性。

  1. *.ps1 text working-tree-encoding=UTF-16

如果您的 * .ps1 文件是UTF-16小端编码而没有BOM,并且您希望Git在工作目录中使用Windows行结尾,请使用以下属性(如果您使用UTF-16-LE-BOM而不是UTF-16LE想要带有BOM的UTF-16小端。请注意,如果使用working-tree-encoding属性来避免歧义,强烈建议使用eol明确定义行结尾。

  1. *.ps1 text working-tree-encoding=UTF-16LE eol=CRLF

您可以使用以下命令获取平台上所有可用编码的列表:

  1. iconv --list

如果您不知道文件的编码,则可以使用file命令猜测编码:

  1. file foo.ps1

ident

当为路径设置属性ident时,Git用$Id:替换blob对象中的$Id$,后跟40个字符的十六进制blob对象名称,然后在结帐时使用美元符号$。任何以$Id:开头并以worktree文件中的$结尾的字节序列在签入时将替换为$Id$

filter

可以将filter属性设置为字符串值,该值指定配置中指定的过滤器驱动程序。

过滤器驱动程序由clean命令和smudge命令组成,其中任何一个都可以不指定。签出时,当指定smudge命令时,命令从其标准输入中提供blob对象,其标准输出用于更新工作树文件。同样,clean命令用于在签入时转换worktree文件的内容。默认情况下,这些命令仅处理单个blob并终止。如果使用长时间运行的process过滤器代替clean和/或smudge过滤器,那么Git可以在单个Git命令的整个生命周期内使用单个过滤器命令调用处理所有blob,例如git add --all。如果配置了长时间运行的process过滤器,则它始终优先于配置的单个blob过滤器。有关用于与process过滤器通信的协议的说明,请参阅以下部分。

内容过滤的一个用途是将内容按摩成对于平台,文件系统和用户更方便使用的形状。对于这种操作模式,这里的关键短语是“更方便”而不是“将某些东西变为无法使用”。换句话说,目的是如果有人取消设置过滤器驱动程序定义,或者没有适当的过滤程序,则该项目仍应可用。

内容过滤的另一个用途是存储无法直接在存储库中使用的内容(例如,引用存储在Git外部的真实内容的UUID,或加密内容),并在检出时将其转换为可用形式(例如,下载外部内容,或解密加密内容)。

这两个过滤器的行为不同,默认情况下,过滤器被视为前者,将内容按摩为更方便的形状。配置中缺少过滤器驱动程序定义,或者以非零状态退出的过滤器驱动程序不是错误,而是使过滤器成为无操作通路。

您可以通过将过滤器< driver> .required配置变量设置为true来声明过滤器将自身无法使用的内容转换为可用内容。

注意:每当更改清理过滤器时,repo应重新规范化:$ git add —renormalize。

例如,在.gitattributes中,您将为路径分配filter属性。

  1. *.c filter=indent

然后,您将在.git / config中定义“filter.indent.clean”和“filter.indent.smudge”配置,以指定一对命令,以便在签入源文件时修改C程序的内容(“clean” “运行”并检出(因为命令是“cat”而没有进行任何更改)。

  1. [filter "indent"]
  2. clean = indent
  3. smudge = cat

为了获得最佳效果,clean如果运行两次(“清洁→清洁”应相当于“清洁”),则不应进一步改变其输出,并且多个smudge命令不应改变clean的输出(“涂抹→涂抹→清洁“应相当于”清洁“)。请参阅下面的合并部分。

“indent”过滤器在这方面表现良好:它不会修改已经正确缩进的输入。在这种情况下,没有污迹过滤器意味着清洁过滤器必须接受自己的输出而不修改它。

如果过滤器必须成功才能使存储的内容可用,您可以在配置中声明过滤器为required

  1. [filter "crypt"]
  2. clean = openssl enc ...
  3. smudge = openssl enc -d ...
  4. required

过滤器命令行上的序列“%f”将替换为过滤器正在处理的文件的名称。过滤器可能会在关键字替换中使用它。例如:

  1. [filter "p4"]
  2. clean = git-p4-filter --clean %f
  3. smudge = git-p4-filter --smudge %f

请注意,“%f”是正在处理的路径的名称。根据要过滤的版本,磁盘上的相应文件可能不存在,或者可能具有不同的内容。因此,涂抹和清除命令不应该尝试访问磁盘上的文件,而只是作为标准输入上提供给它们的内容的过滤器。

长时间运行的过滤器

如果通过filter.&lt;driver&gt;.process定义过滤器命令(字符串值),则Git可以在单个Git命令的整个生命周期内使用单个过滤器调用处理所有blob。这是通过使用长时间运行的进程协议(在technical / long-running-process-protocol.txt中描述)实现的。

当Git遇到需要清理或污迹的第一个文件时,它会启动过滤器并执行握手。在握手中,Git发送的欢迎消息是“git-filter-client”,只支持版本2,支持的功能是“干净”,“涂抹”和“延迟”。

然后Git发送一个以flush数据包终止的“key = value”对列表。该列表至少包含filter命令(基于支持的功能)以及要相对于存储库根目录进行筛选的文件的路径名。在刷新数据包之后,Git发送内容分为零个或多个pkt-line数据包和一个刷新数据包以终止内容。请注意,过滤器在收到内容和最终刷新数据包之前不得发送任何响应。另请注意,“key = value”对的“值”可以包含“=”字符,而键永远不会包含该字符。

  1. packet: git> command=smudge
  2. packet: git> pathname=path/testfile.dat
  3. packet: git> 0000
  4. packet: git> CONTENT
  5. packet: git> 0000

期望过滤器响应一个以flush数据包终止的“key = value”对的列表。如果过滤器没有遇到问题,则列表必须包含“成功”状态。在这些数据包之后,预期过滤器将在最后发送零个或多个pkt-line数据包和一个flush数据包的内容。最后,期望用刷新数据包终止的第二个“key = value”对列表。过滤器可以更改第二个列表中的状态,或者将状态保持为空列表。请注意,无论如何,必须使用flush数据包终止空列表。

  1. packet: git< status=success
  2. packet: git< 0000
  3. packet: git< SMUDGED_CONTENT
  4. packet: git< 0000
  5. packet: git< 0000 # empty list, keep "status=success" unchanged!

如果结果内容为空,则期望过滤器以“成功”状态和刷新分组响应以发信号通知空内容。

  1. packet: git< status=success
  2. packet: git< 0000
  3. packet: git< 0000 # empty content!
  4. packet: git< 0000 # empty list, keep "status=success" unchanged!

如果过滤器不能或不想处理内容,则应该以“错误”状态响应。

  1. packet: git< status=error
  2. packet: git< 0000

如果过滤器在处理过程中遇到错误,则可以在(部分或完全)发送内容后发送状态“错误”。

  1. packet: git< status=success
  2. packet: git< 0000
  3. packet: git< HALF_WRITTEN_ERRONEOUS_CONTENT
  4. packet: git< 0000
  5. packet: git< status=error
  6. packet: git< 0000

如果过滤器不能或不想处理内容以及Git过程生命周期内的任何未来内容,则期望在协议中的任何点以“中止”状态响应。

  1. packet: git< status=abort
  2. packet: git< 0000

如果设置了“错误”/“中止”状态,Git既不会停止也不会重新启动过滤器进程。但是,Git根据filter.&lt;driver&gt;.required标志设置其退出代码,模仿filter.&lt;driver&gt;.clean / filter.&lt;driver&gt;.smudge机制的行为。

如果过滤器在通信期间死亡或者不遵守协议,那么Git将停止过滤器进程并使用下一个需要处理的文件重新启动它。根据filter.&lt;driver&gt;.required标志,Git会将其解释为错误。

延迟

如果过滤器支持“延迟”功能,那么Git可以在过滤器命令和路径名之后发送标志“can-delay”。该标志表示过滤器可以通过响应没有内容但具有状态“延迟”和刷新分组来延迟过滤当前blob(例如,以补偿​​网络延迟)。

  1. packet: git> command=smudge
  2. packet: git> pathname=path/testfile.dat
  3. packet: git> can-delay=1
  4. packet: git> 0000
  5. packet: git> CONTENT
  6. packet: git> 0000
  7. packet: git< status=delayed
  8. packet: git< 0000

如果过滤器支持“延迟”功能,则它必须支持“list_available_blobs”命令。如果Git发送此命令,那么过滤器应该返回一个路径名列表,这些路径名表示先前已经延迟并且现在可用的blob。该列表必须以刷新数据包结束,然后是“成功”状态,该状态也以刷新数据包终止。如果延迟路径的blob尚未可用,则过滤器应该阻止响应,直到至少有一个blob可用。过滤器可以通过发送空列表告诉Git它没有更多延迟的blob。一旦过滤器响应空列表,Git就会停止询问。 Git此时未收到的所有blob都被视为缺失,并将导致错误。

  1. packet: git> command=list_available_blobs
  2. packet: git> 0000
  3. packet: git< pathname=path/testfile.dat
  4. packet: git< pathname=path/otherfile.dat
  5. packet: git< 0000
  6. packet: git< status=success
  7. packet: git< 0000

Git收到路径名后,会再次请求相应的blob。这些请求包含路径名和空内容部分。如上所述,期望过滤器以通常的方式响应污迹内容。

  1. packet: git> command=smudge
  2. packet: git> pathname=path/testfile.dat
  3. packet: git> 0000
  4. packet: git> 0000 # empty content!
  5. packet: git< status=success
  6. packet: git< 0000
  7. packet: git< SMUDGED_CONTENT
  8. packet: git< 0000
  9. packet: git< 0000 # empty list, keep "status=success" unchanged!

可以在位于Git核心存储库中的contrib/long-running-filter/example.pl中找到长时间运行的过滤器演示实现。如果您开发自己的长时间运行过滤器过程,那么GIT_TRACE_PACKET环境变量对调试非常有用(参见 git [1] )。

请注意,您不能将现有的filter.&lt;driver&gt;.cleanfilter.&lt;driver&gt;.smudge命令与filter.&lt;driver&gt;.process一起使用,因为前者使用的是与后者不同的进程间通信协议。

签入/签出属性之间的交互

在签入代码路径中,首先使用filter驱动程序转换worktree文件(如果指定并定义相应的驱动程序),然后使用ident(如果指定)处理结果,最后使用text处理(再次) ,如果指定和适用)。

在签出代码路径中,首先使用text转换blob内容,然后使用ident转换为filter

合并具有不同签入/签出属性的分支

如果您为文件添加了导致该文件的规范存储库格式更改的属性,例如添加clean / smudge过滤器或text / eol / ident属性,那么合并属性不存在的任何内容通常会导致合并冲突。

为了防止这些不必要的合并冲突,可以告诉Git在通过设置merge.renormalize配置变量解析三向合并时运行文件的所有三个阶段的虚拟签出和签入。当转换后的文件与未转换的文件合并时,这可以防止由签入转换引起的更改导致虚假合并冲突。

只要“涂抹→清洁”产生与“干净”相同的输出,即使对于已经弄脏的文件,此策略也会自动解决所有与过滤器相关的冲突。不以这种方式操作的过滤器可能会导致必须手动解决的其他合并冲突。

生成差异文本

diff

属性diff影响Git如何为特定文件生成差异。它可以告诉Git是为路径生成文本补丁还是将路径视为二进制文件。它还可以影响在hunk header @@ -k,l +n,m @@行上显示的行,告诉Git使用外部命令生成diff,或者在生成diff之前让Git将二进制文件转换为文本格式。

  1. Set

设置diff属性的路径被视为文本,即使它们包含通常永远不会出现在文本文件中的字节值,例如NUL。

  1. Unset

未设置diff属性的路径将生成Binary files differ(如果启用了二进制补丁,则生成二进制补丁)。

  1. Unspecified

首先指定diff属性未指定的路径检查其内容,如果它看起来像文本并且小于core.bigFileThreshold,则将其视为文本。否则会产生Binary files differ

  1. String

使用指定的diff驱动程序显示Diff。每个驱动程序可以指定一个或多个选项,如以下部分所述。 diff驱动程序“foo”的选项由Git配置文件的“diff.foo”部分中的配置变量定义。

定义外部差异驱动程序

diff驱动程序的定义是在gitconfig中完成的,而不是gitattributes文件,所以严格来说这个手册页是一个错误的地方来讨论它。然而…

要定义外部差异驱动程序jcdiff,请在$GIT_DIR/config文件(或$HOME/.gitconfig文件)中添加一个部分,如下所示:

  1. [diff "jcdiff"]
  2. command = j-c-diff

当Git需要显示diff属性设置为jcdiff的路径的diff时,它会调用您使用上述配置指定的命令,即j-c-diff,带有7个参数,就像调用GIT_EXTERNAL_DIFF程序一样。有关详细信息,请参阅 git [1]

定义自定义的hunk-header

文本差异输出中的每组更改(称为“hunk”)都以以下形式的行为前缀:

  1. @@ -k,l +n,m @@ TEXT

这称为块头。默认情况下,“TEXT”部分是以字母,下划线或美元符号开头的行;这匹配GNU diff -p 输出使用的内容。但是,此默认选择不适用于某些内容,您可以使用自定义模式进行选择。

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

  1. *.tex diff=tex

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

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

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

有一些内置模式可以使这更容易,tex就是其中之一,因此您不必在配置文件中编写上述内容(您仍然需要通过属性机制通过.gitattributes启用它])。可以使用以下内置模式:

  • ada适用于Ada语言的源代码。

  • bibtex适用于带有BibTeX编码参考的文件。

  • cpp适用于C和C ++语言的源代码。

  • csharp适用于C#语言的源代码。

  • css适用于级联样式表。

  • fortran适用于Fortran语言的源代码。

  • fountain适用于Fountain文档。

  • golang适用于Go语言的源代码。

  • html适用于HTML / XHTML文档。

  • java适用于Java语言的源代码。

  • matlab适用于MATLAB语言的源代码。

  • objc适用于Objective-C语言的源代码。

  • pascal适用于Pascal / Delphi语言的源代码。

  • perl适用于Perl语言的源代码。

  • php适用于PHP语言的源代码。

  • python适用于Python语言的源代码。

  • ruby适用于Ruby语言的源代码。

  • tex适用于LaTeX文档的源代码。

自定义单词差异

您可以通过在“diff。*。wordRegex”配置变量中指定适当的正则表达式来自定义git diff --word-diff用于分割行中单词的规则。例如,在TeX中,反斜杠后跟一系列字母形成一个命令,但是几个这样的命令可以一起运行而不会插入空格。要分隔它们,请在$GIT_DIR/config文件(或$HOME/.gitconfig文件)中使用正则表达式,如下所示:

  1. [diff "tex"]
  2. wordRegex = "\\\\[a-zA-Z]+|[{}]|\\\\.|[^\\{}[:space:]]+"

为上一节中列出的所有语言提供了内置模式。

执行二进制文件的文本差异

有时需要查看某些二进制文件的文本转换版本的差异。例如,可以将文字处理器文档转换为ASCII文本表示,并显示文本的差异。即使这种转换失去了一些信息,生成的差异对人类观看也很有用(但不能直接应用)。

textconv配置选项用于定义执行此类转换的程序。程序应该采用单个参数,要转换的文件的名称,并在stdout上生成结果文本。

例如,要显示文件的exif信息的差异而不是二进制信息(假设您已安装exif工具),请将以下部分添加到$GIT_DIR/config文件(或$HOME/.gitconfig文件):

  1. [diff "jpg"]
  2. textconv = exif

| 注意 | 文本转换通常是单向转换;在这个例子中,我们丢失了实际的图像内容,只关注文本数据。这意味着textconv生成的差异是而不是适合应用。因此,只有git diffgit log系列命令(即log,whatchanged,show)才能执行文本转换。 git format-patch永远不会生成此输出。如果你想向某人发送二进制文件的文本转换差异(例如,因为它会快速传达你所做的更改),你应该单独生成它并将其作为注释发送除了您可能发送的常用二进制差异。 |

因为文本转换速度很慢,特别是在使用git log -p进行大量转换时,Git提供了一种缓存输出并在将来的差异中使用它的机制。要启用缓存,请在diff驱动程序的配置中设置“cachetextconv”变量。例如:

  1. [diff "jpg"]
  2. textconv = exif
  3. cachetextconv = true

这将缓存每个blob上无限期运行“exif”的结果。如果更改diff驱动程序的textconv配置变量,Git将自动使缓存条目无效并重新运行textconv过滤器。如果你想手动使缓存失效(例如,因为你的“exif”版本已更新并且现在产生更好的输出),你可以用git update-ref -d refs/notes/textconv/jpg手动删除缓存(其中“jpg”是差异驱动程序的名称,如上例所示)。

选择textconv与外部差异

如果要在存储库中显示二进制或特殊格式的blob之间的差异,可以选择使用外部diff命令,或使用textconv将它们转换为可扩展的文本格式。您选择哪种方法取决于您的具体情况。

使用外部diff命令的优点是灵活性。您不一定要找到面向行的更改,输出也不一定要像统一的diff那样。您可以以最合适的方式为数据格式定位和报告更改。

相比之下,textconv更具限制性。您提供了将数据转换为面向行的文本格式,Git使用其常规diff工具生成输出。选择此方法有几个好处:

  1. 便于使用。编写二进制文本转换通常要比执行自己的diff更简单。在许多情况下,现有程序可以用作textconv过滤器(例如,exif,odt2txt)。

  2. Git diff功能。通过自己仅执行转换步骤,您仍然可以利用Git的许多差异功能,包括着色,字差异和合并差异进行合并。

  3. 缓存。 Textconv缓存可以加速重复的差异,例如您可能通过运行git log -p触发的差异。

将文件标记为二进制文件

Git通常通过检查内容的开头来正确猜测blob是否包含文本或二进制数据。但是,有时您可能希望覆盖其决定,因为blob在文件中稍后包含二进制数据,或者因为内容虽然在技术上由文本字符组成,但对于人类读者来说是不透明的。例如,许多postscript文件仅包含ASCII字符,但会产生嘈杂且无意义的差异。

将文件标记为二进制文件的最简单方法是取消设置.gitattributes文件中的diff属性:

  1. *.ps -diff

这将导致Git生成Binary files differ(或二进制补丁,如果启用了二进制补丁)而不是常规差异。

但是,也可能需要指定其他diff驱动程序属性。例如,您可能希望使用textconv将postscript文件转换为ASCII表示形式以供人工查看,但另外将其视为二进制文件。您不能同时指定-diffdiff=ps属性。解决方案是使用diff.*.binary配置选项:

  1. [diff "ps"]
  2. textconv = ps2ascii
  3. binary = true

执行三向合并

merge

git merge期间需要文件级合并以及git revertgit cherry-pick等其他命令时,属性merge会影响文件的三个版本的合并方式。

  1. Set

内置的3路合并驱动程序用于以类似于RCS套件的 merge 命令的方式合并内容。这适用于普通文本文件。

  1. Unset

将当前分支中的版本作为暂定合并结果,并声明合并存在冲突。这适用于没有明确定义的合并语义的二进制文件。

  1. Unspecified

默认情况下,它使用与设置merge属性时相同的内置3向合并驱动程序。但是,merge.default配置变量可以将不同的合并驱动程序命名为与未指定merge属性的路径一起使用。

  1. String

使用指定的自定义合并驱动程序执行3向合并。可以通过询问“text”驱动程序明确指定内置的3路合并驱动程序;可以使用“二进制”来请求内置的“取当前分支”驱动程序。

内置合并驱动程序

定义了一些内置的低级合并驱动程序,可以通过merge属性询问。

  1. text

通常的3向文件级合并文本文件。冲突区域标有冲突标记&lt;&lt;&lt;&lt;&lt;&lt;&lt;=======&gt;&gt;&gt;&gt;&gt;&gt;&gt;。分支的版本显示在=======标记之前,合并分支的版本显示在=======标记之后。

  1. binary

保留工作树中的分支版本,但保留路径处于冲突状态以供用户进行整理。

  1. union

对文本文件运行3向文件级别合并,但从两个版本中获取行,而不是留下冲突标记。这往往会以随机顺序在结果文件中保留添加的行,用户应验证结果。如果您不理解其含义,请不要使用此功能。

定义自定义合并驱动程序

合并驱动程序的定义在.git/config文件中完成,而不是在gitattributes文件中完成,因此严格来说,这个手册页是一个错误的地方来讨论它。然而…

要定义自定义合并驱动程序filfre,请在$GIT_DIR/config文件(或$HOME/.gitconfig文件)中添加一个部分,如下所示:

  1. [merge "filfre"]
  2. name = feel-free merge driver
  3. driver = filfre %O %A %B %L %P
  4. recursive = binary

merge.*.name变量为驱动程序提供了一个人类可读的名称。

merge.*.driver变量的值用于构造运行以合并祖先版本(%O),当前版本(%A)和其他分支版本(%B)的命令。在构建命令行时,这三个标记将替换为保存这些版本内容的临时文件的名称。此外,%L将替换为冲突标记大小(见下文)。

合并驱动程序应该通过覆盖它来将合并的结果留在以%A命名的文件中,如果它设法干净地合并它们,则退出为零状态,如果存在冲突则为非零。

merge.*.recursive变量指定当共同驱动器被调用以在共同祖先之间进行内部合并时,要使用的其他合并驱动程序。如果未指定,则驱动程序本身用于内部合并和最终合并。

合并驱动程序可以通过占位符%P了解合并结果的路径名。

conflict-marker-size

此属性控制冲突合并期间留在工作树文件中的冲突标记的长度。仅将值设置为正整数具有任何有意义的效果。

例如,.gitattributes中的这一行可用于告诉合并机器在合并文件Documentation/git-merge.txt导致冲突时留下更长的时间(而不是通常的7个字符长)冲突标记。

  1. Documentation/git-merge.txt conflict-marker-size=32

检查空白错误

whitespace

core.whitespace配置变量允许您定义 diff适用应该考虑项目中所有路径的空白错误(参见 git-config [1] )。此属性为每个路径提供更精细的控制。

  1. Set

注意Git已知的所有类型的潜在空白错误。标签宽度取自core.whitespace配置变量的值。

  1. Unset

不要注意任何错误。

  1. Unspecified

使用core.whitespace配置变量的值来确定要注意的错误。

  1. String

以与core.whitespace配置变量相同的格式指定逗号单独的常见空白问题列表。

创建档案

export-ignore

具有export-ignore属性的文件和目录不会添加到存档文件中。

export-subst

如果为文件设置了属性export-subst,那么在将此文件添加到存档时,Git将展开多个占位符。扩展取决于提交ID的可用性,即,如果 git-archive [1] 已被赋予树而不是提交或标记,则不会进行替换。占位符与 git-log [1] 的选项--pretty=format:的占位符相同,只是它们需要像这样包装:文件中的$Format:PLACEHOLDERS$。例如。字符串$Format:%H$将被提交哈希替换。

包装物

delta

对于属性delta设置为false的路径,不会尝试对blob进行增量压缩。

在GUI工具中查看文件

encoding

此属性的值指定GUI工具应使用的字符编码(例如 gitk [1]git-gui [1] )以显示相关文件的内容。请注意,由于性能方面的考虑, gitk [1] 不使用此属性,除非您在其选项中手动启用每个文件编码。

如果未设置此属性或具有无效值,则使用gui.encoding配置变量的值(参见 git-config [1] )。

使用宏观属性

您不希望应用任何行尾转换,也不希望为您跟踪的任何二进制文件生成文本差异。您需要指定例如

  1. *.jpg -text -diff

但是当你有很多属性时,这可能会变得很麻烦。使用宏属性,您可以定义一个属性,该属性在设置时还可以同时设置或取消设置许多其他属性。系统知道内置的宏属性binary

  1. *.jpg binary

如上所述,设置“binary”属性也会取消设置“text”和“diff”属性。请注意,宏属性只能是“设置”,但设置一个可能具有设置或取消设置其他属性或甚至将其他属性返回到“未指定”状态的效果。

定义宏观属性

自定义宏属性只能在顶级gitattributes文件($GIT_DIR/info/attributes,工作树顶层的.gitattributes文件或全局或系统范围的gitattributes文件)中定义,而不能在.gitattributes文件中定义。工作树子目录。内置的宏属性“binary”相当于:

  1. [attr]binary -diff -merge -text

例子

如果您有这三个gitattributes文件:

  1. (in $GIT_DIR/info/attributes)
  2. a* foo !bar -baz
  3. (in .gitattributes)
  4. abc foo bar baz
  5. (in t/.gitattributes)
  6. ab* merge=filfre
  7. abc -foo -bar
  8. *.c frotz

给路径t/abc的属性计算如下:

  1. 通过检查t/.gitattributes(与相关路径在同一目录中),Git发现第一行匹配。 merge属性已设置。它还发现第二行匹配,并且未设置属性foobar

  2. 然后它检查.gitattributes(在父目录中),并发现第一行匹配,但t/.gitattributes文件已经决定了如何将mergefoobar属性赋予此路径,所以它使foobar未设置。属性baz已设置。

  3. 最后它检查了$GIT_DIR/info/attributes。此文件用于覆盖树内设置。第一行是匹配,foo设置,bar恢复为未指定状态,baz未设置。

结果,分配给t/abc的属性变为:

  1. foo set to true
  2. bar unspecified
  3. baz set to false
  4. merge set to string value "filfre"
  5. frotz unspecified

也可以看看

git-check-attr [1]

GIT

部分 git [1] 套件