Почему 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.