Чому 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

1
На сторінці lsв Mac OS X: Якщо файл або каталог мають розширені атрибути, за полем дозволу, надрукованим -lпараметром, слідує @символ . Скористайтеся опцією, -@щоб переглянути ці розширені атрибути.
adl

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

4
@ nacho4d: Це дивно, адже git навіть не повинен знати, що є якісь розширені атрибути. Якщо ви зможете його відтворити, варто було б внести їх до списку розсилки git. Як це добре в vger.kernel.orgсписках, вам не потрібно підписуватися на публікацію (люди будуть тримати вас CC'ed для відповідей) і начебто не повинні надавати досить високий обсяг git@vger.kernel.orgсписку.
Ян Худек

Відповіді:


76

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

Оглянувши вміст файлу, він побачив матеріал, який не є основними символами ascii. Будучи UTF16, я очікую, що у нього будуть "смішні" персонажі, тому він вважає, що це двійкове.

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

Редагувати: швидкий пошук SO знайденого can-i-make-git -pozna-a-utf-16-file-as-text тексту, який повинен дати вам декілька підказок.


10
Ви майже, але не зовсім не помиляєтесь. Git перевірив фактичні файли та побачив там "смішних" персонажів. Однак це не "думає", що UTF-16 є двійковим. Він є двійковим, оскільки текст визначається як ASCII (це єдине, що вбудований розріз дасть корисні результати для), а UTF-16 - ні. Так, є спосіб сказати git використовувати спеціальний diff для файлів, визначених шаблоном (використовуючи .gitattributes).
Ян Худек

2
Додам, що "смішні персонажі" справді означають нульові байти.
Ян Худек

4
Ми обидва праві, але з різних точок зору. Ми обидва кажемо, що "Git перевіряє вміст, щоб визначити його тип". Ми обидва кажемо, що для того, щоб знати git, це слід трактувати як UTF16, користувачеві потрібно повідомити git via .gitattributesetc.
Philip Oakley

7
@JanHudec: На ваш погляд, усі файли є двійковими.
stolsvik

2
@stolosvik, (і JanH) Це більш тонка середня позиція в тому, що UTF-8 включає як базові символи 0-127 ASCII, так і всі інші символи Unicode, без необхідності нульового (00h) байта для чогось іншого, крім нульової таблиці (термінальний рядок 'C'). Таким чином, визначення тексту Гіта полягає в тому, що вміст (добре перші 1 байти) не повинен мати нульовий байт, коли закодовано 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 як бінарні, і тому не міг побачити різницю

Створення файлу з назвою "атрибути" у папці .git \ info із наступним вмістом вирішило проблему

*.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 навіть визначить, що він є двійковим, якщо у вашому текстовому файлі є один дуже довгий рядок. Я розірвав довгу рядок, перетворивши її на кілька рядків вихідного коду, і раптом файл перейшов із «двійкового» у текстовий файл, який я міг бачити (у SmartGit).

Тому не продовжуйте вводити занадто далеко вправо, не натискаючи "Enter" у своєму редакторі - інакше пізніше Git подумає, що ви створили двійковий файл.


1
Це правильна інформація. Я намагався керувати різницею для надзвичайно великого дампа MySQL (.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 ++, щоб легко переглядати та змінювати тип кодування текстового файлу; Відкрийте файл у «Блокноті ++» та скористайтеся меню «Кодування» на панелі інструментів.


1
Unicode не є кодуванням. Це набір, і UTF-8 - це одне з його кодування, тобто спосіб кодування кодової точки Unicode
phuclv

1
Це не вирішує питання, а лише уникає його. Проблема полягає в тому, що git або його різний інструмент неправильно розпізнає текстові файли або не дозволяє користувачеві легко переосмислювати його поведінку.
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 покаже бінарні зміни.


Аналогічно з одним або двома (успішно складеними) файлами cpp, висунутими з VS. Здійснює гуй 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 з кодуванням BOM . Зміна кодування на звичайний UTF-8 негайно змусила Git бачити файл як type = text


1

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

Цей файл був визначений як двійковий за допомогою git. Додавання .gitattributesфайлу допомогло.

# .gitattributes file
.gitignore diff

1
Працювали. У мене також був подвійний \ r, щоб ігнорувати якийсь файл ОС «Ікона \ r \ r». Добре знати причину, а також виправити.
hsandt

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.