【问题标题】:How to find out why a file has been deemed text or binary by git for EOL conversion?如何找出为什么文件被 git 视为文本或二进制文件以进行 EOL 转换?
【发布时间】:2019-01-14 10:13:10
【问题描述】:

如果存储库中存在 .gitattributes 或设置了配置选项以启用行尾 (EOL) 转换,git 需要确定文件是 text 还是 binary .

有时这个决定并不明显,例如如果文件中存在不可见字符,请参阅https://confluence.atlassian.com/bbkb/file-detected-as-binary-not-displayed-as-text-in-bitbucket-892611499.html 示例。

在大多数情况下,您可能想要修复导致文件被识别为不是的字符的存在。但是,链接帖子中提出的使用hexdumpvi 的分析可能是详尽无遗的,对于某些文件和/或用户来说几乎是不可能的。有没有办法找出是什么原因导致git 将文件识别为文本或二进制文件(例如“由于 [n] 行存在 [some codepoint] 而将 [path] 重新识别为二进制文件”)?

我们的团队在 Ubuntu 18.10、Windows 10 和 macOS 上使用 Git 2.19 和 2.17。

【问题讨论】:

    标签: git line-endings eol


    【解决方案1】:

    git 依赖于其xdiff-interface.c 文件中的buffer_is_binary 来决定文件是二进制文件还是文本文件。该函数是从 Git 的合并代码以及其他地方调用的。逻辑很简单 - 如果文件的第一个 8000 字节中有一个 0 字节,则该文件是二进制文件。代码是:

    #define FIRST_FEW_BYTES 8000
    int buffer_is_binary(const char *ptr, unsigned long size)
    {
        if (FIRST_FEW_BYTES < size)
            size = FIRST_FEW_BYTES;
        return !!memchr(ptr, 0, size);
    }
    

    因此,如果文件以 UTF-16 编码,您可以将非常简单的文件检测为二进制文件,这是 Git 将文件视为二进制文件的常见原因。包含

    的文本文件
    a b
    

    如果以 UTF-16 格式保存,将被检测为二进制,因为它的 hexdump 输出是,LF 文件结尾:

    0000000 6100 2000 6200 0a00
    

    例如,空格(ASCII 或 UTF-8 中的0x20)在 UTF-16 中被编码为 0x0020,因此 Git 认为文件是二进制的。

    所以“详细”模式并没有太大帮助,因为您需要定位 0 字节。 grep 可以在 Perl-regex 模式下执行此操作,例如 grep -obaUP "\x00" filename 以打印 0-value 字节的字节偏移量。

    【讨论】:

    • 宝贵意见,谢谢。前 8000 个字节中没有 0 字节是否意味着该文本应该被视为文本?我的测试用例是.gitattributes 中的* text eol=lf 的存储库,其中git 想要在.jar.git 中的git rm --cached -r . &amp;&amp; git add . 之后更改换行符,根据提供的grep,它们都包含0 字节测试。
    • 我认为.gitattributes 只会覆盖检测。但是,text 属性主要用于行尾。它仍然会在几个地方具有二进制行为,例如差异时。您可能想要设置 diff 属性,例如* diff.
    【解决方案2】:

    git ls-files --eol 显示有关 git 如何识别文件以及如何提交文件的信息:

    --eol

    显示和文件。是“text”属性为“auto”(或未设置且 core.autocrlf 不为 false)时 Git 使用的文件内容标识。是“-text”、“none”、“lf”、“crlf”、“mixed”或“”。

    "" 表示该文件不是常规文件,它不在索引中或在工作树中不可访问。

    是签出或提交时使用的属性,它可以是“”、“-text”、“text”、“text=auto”、“text eol=lf”、“text eol=crlf”。从 Git 2.10 开始支持“text=auto eol=lf”和“text=auto eol=crlf”。

    对于常规文件,索引中的 ("i/") 和工作树中的 ("w/") 都会显示,然后是 ("attr/")。

    来自git ls-files documentation

    【讨论】:

      猜你喜欢
      • 2011-10-14
      • 1970-01-01
      • 1970-01-01
      • 2013-08-20
      • 1970-01-01
      • 2020-06-07
      • 1970-01-01
      • 2016-08-18
      相关资源
      最近更新 更多