为什么Git将此文本文件视为二进制文件?


150

我不知道为什么git告诉我这个?

$ git diff MyFile.txt
diff --git a/MyFile.txt b/MyFile.txt
index d41a4f3..15dcfa2 100644
Binary files a/MyFile.txt and b/MyFile.txt differ

他们不是文本文件吗?

我已经检查了.gitattributes,它为空。为什么我收到此消息?我再也无法获得差异

添加:

我注意到@文件中有一个权限,这是什么?这可能是原因吗?

$ls -all
drwxr-xr-x   5 nacho4d  staff    170 28 Jul 17:07 .
drwxr-xr-x  16 nacho4d  staff    544 28 Jul 16:39 ..
-rw-r--r--@  1 nacho4d  staff   6148 28 Jul 16:15 .DS_Store
-rw-r--r--@  1 nacho4d  staff    746 28 Jul 17:07 MyFile.txt
-rw-r--r--   1 nacho4d  staff  22538  5 Apr 16:18 OtherFile.txt

4
它可能是UTF-8编码的文件。
Marnix van Valen

它应该是UTF16小尾数LF
nacho4d 2011年

1
ls在Mac OS X 的联机帮助页上:如果文件或目录具有扩展属性,则该-l选项打印的权限字段后跟一个@字符。使用选项-@查看这些扩展属性。
ADL

我认为这可能是git的错误。我删除了扩展属性,现在一切恢复正常。
nacho4d 2011年

4
@ nacho4d:这很奇怪,因为git甚至都不知道有任何扩展属性。如果您可以复制它,则值得在git邮件列表中进行。按照vger.kernel.org列表上的习惯,您不必订阅帖子(人们会一直在抄送您的答案),并且应该避免git@vger.kernel.org列表的数量过多。
1月Hudec

Answers:


76

它仅表示git检查文件的实际内容时(它不知道任何给定的扩展名不是二进制文件-如果要明确告诉它,则可以使用属性文件-请参见手册页)。

检查了文件的内容后,发现文件中没有基本的ascii字符。作为UTF16,我希望它具有“有趣”字符,因此它认为它是二进制的。

有几种方法可以告诉git您是否具有文件的国际化(i18n)或扩展字符格式。我没有足够的确切方法来设置-您可能需要RT [Full] M ;-)

编辑:SO的快速搜索发现可以使我做一个git-recognize-a-utf-16文件作为文本,这应该给您一些提示。


10
您几乎但并非完全没有错。Git确实检查了实际文件,并在那里看到“有趣”字符。但是,它不会“认为” UTF-16是二进制的。它二进制的,因为文本被定义为基于ASCII的代码(这是内置diff将提供可用结果的唯一内容),而UTF-16则不是。是的,有一种方法可以告诉git对模式定义的文件使用特殊的diff(使用.gitattributes)。
1月Hudec

2
我应该补充一点,“有趣的字符”实际上意味着零字节。
Jan Hudec

4
我们都是对的,但是从不同的角度来看。我们都说“ Git检查内容以确定其类型。” 我们都表示,为了使混帐知道它应该被视为UTF-16用户需要告诉git的通过.gitattributes
菲利普·奥克利

7
@JanHudec:在您看来,所有文件都是二进制文件。
stolsvik '16

2
@stolosvik,(和JanH)这是一个更微妙的中间立场,因为UTF-8既包含基本的0-127个ASCII字符,也包括所有其他Unicode字符,而对于nul字符以外的任何内容都不需要空(00h)字节(“ C”字符串终止符)。因此,Git的文本定义是,当utf-8编码时,内容(以及前1k字节)不应具有空字节。尝试stackoverflow.com/questions/2241348/…以获得有趣的阅读。我原来的注释是指当UTF-16编码数据被看作字节对,所以对于ascii码点的高字节将是00的情况下
菲利普·奥克利

41

如果您尚未设置文件的类型,则Git会尝试自动确定文件的类型,并将具有很长行且可能包含一些宽字符(例如Unicode)的文件视为二进制文件。使用.gitattributes文件,您可以定义Git解释文件的方式。手动设置diff属性可以使Git将文件内容解释为文本,并会执行通常的diff操作。

只需将.gitattributes添加到您的存储库根文件夹,并将diff属性设置为路径或文件。这是一个例子:

src/Acme/DemoBundle/Resources/public/js/i18n/* diff
doc/Help/NothingToSay.yml                      diff
*.css                                          diff

如果要检查文件上是否设置了属性,可以在git check-attr的帮助下进行

git check-attr --all -- src/my_file.txt

关于Git属性的另一个很好的参考可以在这里找到。


1
这很有用,但实际上是不正确的-正确的属性是diff,不是text。该text属性不会告诉git使用文本进行差异化,而是控制行尾的处理方式(对LF的标准化)。有关更多详细信息,请参见指向.gitattributes的链接。
ErikE 2014年

谢谢@ErikE。我已经根据您的评论和Git文档更新了我的帖子。
naitsirch 2014年

4
此外,您可以设置应该执行哪种比较。例如,如果它是xml文件,则可以使用diff=xml而不是diff
桑迪·查普曼

1
check-attr的反面是-有set-attr吗?我最初不小心将文件另存为UTF-16,然后提交并推送了它,现在,即使将其重新保存为UTF-8,然后再次提交并推送,BitBucket仍将其视为UTF-16。这基本上使我的请求请求无法阅读,因为审阅者需要单击每个单独的评论来添加审阅评论。
John Zabroski

21

我遇到的问题是Git GUI和SourceTree将Java / JS文件视为二进制文件,因此看不到区别

使用以下内容在.git \ info文件夹中创建名为“ attributes”的文件可解决此问题

*.java diff
*.js diff
*.pl diff
*.txt diff
*.ts diff
*.html diff

如果要对所有存储库进行此更改,则可以在以下位置$ HOME / .config / git / attributes中添加属性文件


1
还要注意<project-root>/.gitattributes文件,该文件使更改对所有贡献者有效,并且仅对相关项目有效。
jpaugh

添加* diff对我很有帮助:它显示了所有类型文件的差异。但是您的解决方案更好,因为可以避免在大型二进制文件中显示不必要的差异。
Boolean_Type

是的 这有帮助!
WildCat

19

如果文本文件中有一条超长行,Git甚至会确定它是二进制的。我分解了一个很长的String,将其转换为多个源代码行,然后突然文件从“二进制”变成了我可以看到的文本文件(在SmartGit中)。

因此,不要在编辑器中未按“ Enter”键的情况下在右侧输入过多的文字-否则稍后Git会认为您已创建了二进制文件。


1
这是正确的信息。我试图将差异控制到一个非常大的MySQL Dump(.sql文件)中,但是git将其视为二进制文件,即使它仅包含ASCII / UTF8数据也是如此。原因是行超长(插入值(一个),(两个),(三个),(...),(300万...);.奇怪的是,对于每次提交,git存储库都会不会增加1.7gb,而只能增加约350mb。也许git在保存之前已经压缩了“二进制”文件
Alexandre T.

@AlexandreT。Git确实可以压缩文件Blob(使用GZip,IIRC)。
jpaugh

11

在新的编辑器中编辑一个文件后,我遇到了同样的问题。原来,新编辑器使用的编码(Unicode)与旧编辑器(UTF-8)不同。因此,我只是简单地告诉新编辑器使用UTF-8保存文件,然后git再次正确显示我的更改,并且没有将其视为二进制文件。

我认为问题仅仅是git不知道如何比较不同编码类型的文件。因此,只要保持一致,您使用的编码类型就没有关系。

我没有测试它,但是我确定如果我使用新的Unicode编码提交文件,那么下次我对该文件进行更改时,它会正确显示更改并且不会将其检测为二进制,因为那么它应该将两个Unicode编码文件而不是UTF-8文件与Unicode文件进行比较。

您可以使用Notepad ++之类的应用轻松查看和更改文本文件的编码类型。在Notepad ++中打开文件,然后使用工具栏中的“编码”菜单。


1
Unicode不是编码。这是一个字符集,UTF-8是其编码之一,即编码Unicode代码点的方式
phuclv

1
这不能解决问题,只能避免。问题是git或其diff工具无法正确识别文本文件,或者不能轻易允许用户覆盖其行为。
Preza8

6

我有同样的问题。我在Google上搜索解决方案时找到了线索,但仍然找不到任何线索。但是我想我经过研究发现了原因,下面的例子将清楚地说明我的线索。

    echo "new text" > new.txt
    git add new.txt
    git commit -m "dummy"

目前,文件new.txt被认为是文本文件。

    echo -e "newer text\000" > new.txt
    git diff

你会得到这个结果

diff --git a/new.txt b/new.txt
index fa49b07..410428c 100644
Binary files a/new.txt and b/new.txt differ

尝试一下

git diff -a

你会得到以下

    diff --git a/new.txt b/new.txt
    index fa49b07..9664e3f 100644
    --- a/new.txt
    +++ b/new.txt
    @@ -1 +1 @@
    -new file
    +newer text^@

5

在这种情况下,每当我们尝试对.html文件进行更改时,该文件都被视为二进制文件。非常不酷,看不到差异。老实说,我没有在这里检查所有解决方案,但是对我们有用的是:

  1. 删除了文件(实际上将其移至我的桌面)并提交了git deletion。吉特说Deleted file with mode 100644 (Regular) Binary file differs
  2. 重新添加文件(实际上将其从我的桌面移回了项目中)。Git说New file with mode 100644 (Regular) 1 chunk, 135 insertions, 0 deletions文件现在被添加为常规文本文件

从现在开始,我对文件所做的任何更改都将被视为常规文本差异。您也可以压缩这些提交(1、2和3是您所做的实际更改),但是我希望将来能够看到自己的所作所为。压扁1和2将显示二进制变化。


与从VS推送的一两个(成功编译)cpp文件类似。渲染Github gui进行比较可笑。在这样的叮当交汇处,不希望有人摇铃,-VS一侧说是Github,而另一侧Github说是VS。:(
Laurie Stearn

4

根据这个有用的答案,您可以直接询问Git为什么以特定方式处理文件:

cd directory/of/interest
file *

它产生如下有用的输出:

$ file *
CR6Series_stats resaved.dat: ASCII text, with very long lines, with CRLF line terminators
CR6Series_stats utf8.dat:    UTF-8 Unicode (with BOM) text, with very long lines, with CRLF line terminators
CR6Series_stats.dat:         ASCII text, with very long lines, with CRLF line terminators
readme.md:                   ASCII text, with CRLF line terminators

6
file不是git命令。它是Windows上与git打包在一起的完全独立的工具。是否有文档显示git用于检测二进制文件?
Max

4

这也是(至少在Windows上)由具有BOM编码的UTF-8的文本文件引起的。立即将编码更改为常规UTF-8,使Git将该文件视为type = text


1

我有一个实例,其中故意.gitignore包含一个双\r(回车)序列。

该文件被git识别为二进制文件。添加.gitattributes文件有帮助。

# .gitattributes file
.gitignore diff

1
工作了 我也有一个双\ r来忽略某些操作系统的“ Icon \ r \ r”文件。很高兴知道原因以及解决方法。
hsandt

1

如果git check-attr --all -- src/my_file.txt表明您的文件已标记为二进制文件,并且尚未将其设置为二进制文件.gitattributes,请在中进行检查/.git/info/attributes


0

将Aux.js更改为另一个名称,例如Sig.js。

源树仍将其显示为二进制文件,但是您可以暂存(添加)并提交。


0

我遇到了类似的问题,因为我从二进制Kafka消息中粘贴了一些文本,该消息插入了不可见的字符,并导致git认为文件是二进制的。

我通过使用regex搜索文件发现了令人讨厌的字符[^ -~\n\r\t]+

  • [ 匹配此集合中的字符
  • ^ 匹配不在此集合中的字符
  • -~ 匹配从''(空格)到'〜'的所有字符
  • \n 新队
  • \r 回车
  • \t 标签
  • ] 接近集
  • + 匹配这些字符中的一个或多个

-2

我只是花了几个小时来仔细研究清单上的所有内容,以弄清楚为什么我的解决方案中的一个测试项目没有向浏览器添加任何测试。

在我的案例中,事实证明(可能是由于某个地方的git合并不良),VS完全失去了对该项目的引用。它仍在构建,但我注意到它仅建立了依赖关系。

然后,我注意到它没有显示在依赖项列表本身中,因此我删除并重新添加了测试项目,最后所有测试都显示了出来。


2
Visual Studio确实与此处无关。
jpaugh
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.