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

Why does Git treat this text file as a binary file?

我想知道为什么Git告诉我:

1
2
3
4
$ 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,它是空的。为什么我收到这个信息?我不能再像以前那样有差异了

补充:

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

1
2
3
4
5
6
$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


这仅仅意味着当Git检查文件的实际内容时(它不知道任何给定的扩展名不是二进制文件-如果您想明确地告诉它,可以使用属性文件-参见手册页)。

在检查了文件的内容之后,它发现了一些不使用基本ASCII字符的内容。作为utf16,我希望它有"有趣"的字符,所以它认为它是二进制的。

有一些方法可以告诉Git文件是否具有国际化(i18n)或扩展字符格式。我没有足够的方法来设置这个-你可能需要rt[完整]m;-)

编辑:快速搜索找到的can-i-make-git-recognize-a-utf-16-file-as-text,这会给你一些线索。


如果您没有设置文件的类型,g it会自动确定它,并且具有很长的行和一些宽字符(例如unicode)的文件会被视为二进制文件。通过.gitattributes文件,您可以定义git如何解释该文件。手动设置diff属性可以让git将文件内容解释为文本,并执行常规的diff。

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

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

如果要检查文件上是否设置了属性,可以在git check attr的帮助下执行该操作。

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

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


我有这个问题,Git GUI和SourceTree把Java/JS文件当作二进制处理,因此看不到区别。

使用以下内容在.gitinfo文件夹中创建名为"attributes"的文件解决了这个问题

1
2
3
4
5
6
*.java diff
*.js diff
*.pl diff
*.txt diff
*.ts diff
*.html diff

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


如果文本文件中有一个超长行,Git甚至会确定它是二进制的。我分解了一个长字符串,把它转换成几个源代码行,突然文件从"二进制"变成了我能看到的文本文件(在smartgit中)。

因此,不要在编辑器中不按Enter键的情况下一直输入太多的内容,否则稍后Git会认为您已经创建了一个二进制文件。


在一个新的编辑器中编辑了一个文件之后,我也遇到了同样的问题。结果发现新的编辑器使用的编码(Unicode)与旧的编辑器(UTF-8)不同。所以我简单地告诉我的新编辑器用UTF-8保存我的文件,然后Git再次正确地显示了我的更改,并没有将其视为二进制文件。

我认为问题只是Git不知道如何比较不同编码类型的文件。因此,只要保持一致,您使用的编码类型实际上并不重要。

我没有测试它,但我确信如果我用新的Unicode编码提交我的文件,下次我对该文件进行更改时,它会正确显示更改,而不会检测到它是二进制的,从那时起,它会比较两个Unicode编码的文件,而不是将UTF-8文件与Unicode文件。

您可以使用类似记事本++的应用程序轻松查看和更改文本文件的编码类型;在记事本++中打开该文件,然后使用工具栏中的"编码"菜单。


我也有同样的问题。我在谷歌上搜索解决方案时发现了这个线索,但我还是没有发现任何线索。但我想我在学习后找到了原因,下面的例子将清楚地解释我的线索。

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

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

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

你会得到这个结果的

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

试试这个

1
git diff -a

你会在下面

1
2
3
4
5
6
7
    diff --git a/new.txt b/new.txt
    index fa49b07..9664e3f 100644
    --- a/new.txt
    +++ b/new.txt
    @@ -1 +1 @@
    -new file
    +newer text^@


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

1
2
cd directory/of/interest
file *

它产生如下有用的输出:

1
2
3
4
5
$ 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


在这种情况下,每当我们试图对.html文件进行更改时,就会将其视为二进制文件。很不酷,看不到差异。老实说,我没有检查所有的解决方案,但对我们有用的是:

  • 已删除文件(实际已将其移动到桌面)并提交git deletion。Git说Deleted file with mode 100644 (Regular) Binary file differs
  • 重新添加文件(实际移动它从我的桌面回到项目中)。Git说New file with mode 100644 (Regular) 1 chunk, 135 insertions, 0 deletions文件现在添加为常规文本文件
  • 从现在开始,我在文件中所做的任何更改都被视为常规文本差异。您也可以挤压这些提交(1、2和3是您所做的实际更改),但我希望以后能够看到我所做的。挤压1和2将显示二进制变化。


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

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

    1
    2
    # .gitattributes file
    .gitignore diff


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


    将aux.js更改为其他名称,如sig.js。

    源代码树仍然将其显示为二进制文件,但是您可以分段(添加)并提交它。


    如果git check-attr --all -- src/my_file.txt表示文件被标记为二进制,而在.gitattributes中没有将其设置为二进制,请在/.git/info/attributes中检查它。


    我花了几个小时浏览了这个列表中的所有内容,试图找出为什么我的解决方案中的一个测试项目没有向资源管理器添加任何测试。

    在我的案例中,结果发现,在某种程度上(可能是因为某个地方的Git合并不好),Vs完全失去了一个参考项目。它还在建,但我注意到它只建立了依赖关系。

    然后我注意到它并没有出现在依赖项列表中,所以我删除并重新添加了测试项目,最终我的所有测试都出现了。