Почему 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, и он пуст. Почему я получаю это сообщение? Я не могу получить diff как я использую больше

ДОБАВЛЕНО:

Я заметил, что @в файле есть права доступа, что это? Может ли это быть причиной?

$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.
Марникс ван Вален

Предполагается, что это UTF16 с прямым порядком байтов LF
nacho4d

1
Из справочнойls страницы в Mac OS X: если файл или каталог имеет расширенные атрибуты, за полем разрешений, напечатанным -lпараметром, следует @символ . Используйте опцию, -@чтобы увидеть эти расширенные атрибуты.
ADL

Я думаю, что это может быть ошибка мерзавца. Я удалил расширенные атрибуты, и теперь все в порядке снова.
nacho4d

4
@ nacho4d: Это странно, потому что git даже не должен знать, что существуют какие-либо расширенные атрибуты. Если бы вы могли воспроизвести его, стоило бы включить его в список рассылки git. Как это принято в vger.kernel.orgсписках, вам не нужно подписываться на посты (люди будут держать вас в CC для ответов), и, скорее всего, они не учитывают достаточно большой объем git@vger.kernel.orgсписка.
Ян Худек

Ответы:


76

Это просто означает, что когда git проверяет фактическое содержимое файла (он не знает, что какое-либо данное расширение не является двоичным файлом - вы можете использовать файл атрибутов, если вы хотите сообщить об этом явно - см. Справочные страницы).

Осмотрев содержимое файла, он увидел вещи, которые не представлены в основных символах ascii. Будучи UTF16, я ожидаю, что в нем будут «забавные» символы, поэтому он думает, что он двоичный.

Есть способы сообщить git, если у вас есть интернационализация (i18n) или расширенные форматы символов для файла. Я недостаточно разбираюсь в точном способе установки этого - вам может понадобиться RT [Full] M ;-)

Изменить: быстрый поиск SO нашел can-i-make-git-признать-a-utf-16-файл-как-текст, который должен дать вам несколько подсказок.


10
Вы почти, но не совсем не ошиблись. Git проверил реальные файлы и увидел там «забавных» персонажей. Однако он не «думает», что UTF-16 является двоичным. Это является двоичным, потому что текст определяется как ASCII-основе (это единственное , что встроенный в дифф даст использовать результаты для) и UTF-16 нет. Да, есть способ указать git использовать специальный diff для файлов, определенных шаблонами (using .gitattributes).
Ян Худек

2
Я должен добавить, что «забавные персонажи» действительно означают ноль байтов.
Ян Худек

4
Мы оба правы, но с разных точек зрения. Мы оба говорим: «Git проверяет содержимое, чтобы определить его тип». Мы оба говорим, что для того, чтобы git знал, что его следует рассматривать как UTF16, пользователь должен сообщить git через .gitattributesт. Д.
Philip Oakley,

7
@JanHudec: По вашему мнению, все файлы являются двоичными.
stolsvik

2
@stolosvik, (и JanH) Это более тонкая золотая середина в том, что UTF-8 включает в себя как базовые символы 0-127 ASCII, так и все другие символы Юникода, без нуля байтов (00h) для чего-либо, кроме nul char (терминатор строки 'C'). Таким образом, текстовое определение Git состоит в том, что содержимое (ну, первые 1k байтов) не должно иметь нулевого байта при кодировании utf-8. Попробуйте 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Атрибут не говорит мерзавцу к дифф с помощью текста , но вместо управления , как строки окончания обрабатываются (нормализация к LF). Смотрите вашу ссылку на .gitattributes для более подробной информации.
ErikE

Спасибо @ErikE. Я обновил свой пост в соответствии с вашим комментарием и документацией Git.
naitsirch

4
Кроме того, вы можете установить, какой тип различий должен выполняться. Например, если это XML-файл, который вы можете использовать diff=xmlвместо просто diff.
Сэнди Чепмен

1
Что является противоположностью check-attr - есть ли set-attr? Первоначально я случайно сохранил файл как UTF-16, затем зафиксировал и выдвинул его, и теперь BitBucket видит его как UTF-16, даже после повторного сохранения его как UTF-8, фиксации и повторного нажатия. Это в основном делает невозможным чтение моих запросов извлечения, потому что рецензенты должны нажимать на каждый отдельный комментарий, чтобы добавить комментарии рецензирования.
Джон Заброски

21

У меня была эта проблема, когда Git GUI и SourceTree обрабатывали файлы Java / JS как двоичные файлы и, следовательно, не могли видеть разницу

Создание файла с именем «attribute» в папке .git \ info со следующим содержимым решило проблему

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

Если вы хотите внести это изменение для всех репозиториев, вы можете добавить файл атрибутов в следующую папку $ HOME / .config / git / attribute


1
Также обратите внимание на <project-root>/.gitattributesфайл, который делает изменение активным для всех участников и только для соответствующего проекта.
jpaugh

Добавление * diffбыло полезно для меня: оно показывает разницу во всех типах файлов. Но ваше решение лучше, потому что нужно избегать показа ненужных различий в больших двоичных файлах.
Boolean_Type

Да! Это помогает!
WildCat

19

Git даже определит, что это двоичный файл, если в вашем текстовом файле есть одна сверхдлинная строка. Я разбил длинную строку, превратив ее в несколько строк исходного кода, и внезапно файл превратился из «двоичного» в текстовый файл, который я мог видеть (в SmartGit).

Поэтому не продолжайте вводить слишком далеко вправо, не нажимая «Enter» в вашем редакторе - иначе позже Git будет думать, что вы создали двоичный файл.


1
Это правильная информация. Я пытался контролировать diff для очень большого MySQL Dump (файл .sql), но git рассматривает его как двоичный файл, даже если он содержит только данные ASCII / UTF8. Причина в том, что строки очень длинные (вставьте значения (один), (два), (три), (...), (3 миллиона ...); как ни странно, для каждого коммита репозиторий git делает не увеличивается на 1,7 ГБ, а только на ~ 350 МБ. Возможно, git сжимает «двоичный» файл перед его сохранением
Александр Т.

@AlexandreT. Git действительно сжимает файловые объекты (используя GZip, IIRC).
jpaugh

11

У меня была такая же проблема после редактирования одного из моих файлов в новом редакторе. Оказывается, новый редактор использовал другую кодировку (Unicode), чем мой старый редактор (UTF-8). Поэтому я просто сказал моему новому редактору сохранить мои файлы с помощью UTF-8, а затем git снова правильно показал мои изменения и не увидел их как двоичный файл.

Я думаю, проблема была в том, что git не знает, как сравнивать файлы разных типов кодирования. Таким образом, тип кодировки, который вы используете, на самом деле не имеет значения, если он остается согласованным.

Я не проверял это, но я уверен, что если бы я просто зафиксировал свой файл с новой кодировкой Unicode, то в следующий раз, когда я внесу изменения в этот файл, он бы показал изменения правильно и не обнаружил его как двоичный, так как тогда он сравнивал бы два файла в кодировке Unicode, а не файл UTF-8 с файлом Unicode.

Вы можете использовать приложение, такое как Notepad ++, чтобы легко увидеть и изменить тип кодировки текстового файла; Откройте файл в Notepad ++ и используйте меню «Кодировка» на панели инструментов.


1
Юникод не является кодировкой. Это кодировка, и UTF-8 - это одна из ее кодировок, то есть способ кодирования
кодовой точки

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 . Git говоритDeleted file with mode 100644 (Regular) Binary file differs
  2. Повторно добавил файл (фактически переместил его из моего рабочего стола обратно в проект). Git говорит, что New file with mode 100644 (Regular) 1 chunk, 135 insertions, 0 deletionsфайл теперь добавлен как обычный текстовый файл

Отныне любые изменения, которые я вносил в файл, воспринимаются как обычный текстовый diff. Вы также можете раздавить эти коммиты (1, 2 и 3 - фактические изменения, которые вы делаете), но я предпочитаю видеть в будущем то, что я сделал. Сквош 1 и 2 покажет двоичное изменение.


Аналогично одному или двум (успешно скомпилированным) файлам cpp, переданным из VS. Оказывает Github GUI для сравнения смешно. Никто не хотел бы быть мухой на звонке в такой развязке динг-донга, - В.С. с одной стороны сказал, что это Github, а с другой стороны Гитхуб сказал, что это VS. :(
Лори Стерн

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. Это совершенно отдельный инструмент, включенный в Git для Windows. Есть ли документация, показывающая, что это то, что git использует для обнаружения двоичных файлов?
Макс

4

Это также вызвано (по крайней мере в Windows) текстовыми файлами с UTF-8 с кодировкой спецификации . Изменение кодировки на обычный UTF-8 немедленно заставило Git увидеть файл как type = text


1

У меня был случай, когда .gitignoreсодержал двойной\r (возврат каретки) последовательность по назначению.

Этот файл был идентифицирован как двоичный файл git. Добавление .gitattributesфайла помогло.

# .gitattributes file
.gitignore diff

1
Работал. У меня также было двойное \ r, чтобы игнорировать некоторые файлы ОС "Icon \ r \ r". Приятно знать причину, а также исправить.
18:30

1

Если git check-attr --all -- src/my_file.txtуказывает, что ваш файл помечен как двоичный, и вы не установили его как двоичный файл .gitattributes, проверьте его /.git/info/attributes.


0

Измените Aux.js на другое имя, например Sig.js.

Дерево исходных текстов по-прежнему показывает его в виде двоичного файла, но вы можете поставить (добавить) его и зафиксировать.


0

У меня была похожая проблема, когда я вставил какой-то текст из двоичного сообщения Kafka, в котором был вставлен невидимый символ, и git решил, что файл является двоичным.

Я нашел оскорбительные символы путем поиска файла с помощью регулярных выражений [^ -~\n\r\t]+.

  • [ сопоставить символы в этом наборе
  • ^ сопоставить символы не в этом наборе
  • -~ соответствует всем символам от '' (пробел) до '~'
  • \n новая линия
  • \r возврат каретки
  • \t табуляция
  • ] закрыть набор
  • + соответствовать одному или нескольким из этих символов

-2

Я просто потратил несколько часов, просматривая все в этом списке, пытаясь понять, почему один из тестовых проектов в моем решении не добавлял никаких тестов в проводник.

В моем случае оказалось, что каким-то образом (вероятно, из-за плохого слияния где-то), что VS потерял ссылку на проект в целом. Это все еще строило, но я заметил, что это только построило зависимости.

Затем я заметил, что он не отображается в самом списке зависимостей, поэтому я удалил и заново добавил тестовый проект, и все мои тесты наконец-то появились.


2
Visual Studio здесь действительно не актуален.
jpaugh
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.