Warum behandelt Git diese Textdatei als Binärdatei?

150

Ich frage mich, warum Git mir das sagt:?

$ 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

Sind sie nicht Textdateien?

Ich habe die .gitattributes überprüft und es ist leer. Warum bekomme ich diese Nachricht? Ich kann keine Unterschiede mehr bekommen, wie ich es gewohnt bin

HINZUGEFÜGT:

Ich habe festgestellt, dass @in der Datei Berechtigungen vorhanden sind. Was ist das? Könnte dies der Grund sein?

$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
nacho4d
quelle
4
Es könnte sich um eine UTF-8-codierte Datei handeln.
Marnix van Valen
Es soll UTF16 Little Endian LF sein
nacho4d
1
Aus der lsManpage unter Mac OS X: Wenn die Datei oder das Verzeichnis erweiterte Attribute hat, -lfolgt auf das von der Option gedruckte Berechtigungsfeld ein @Zeichen . Verwenden Sie die Option -@, um diese erweiterten Attribute anzuzeigen.
adl
Ich denke, das könnte ein Fehler sein. Ich habe die erweiterten Attribute gelöscht und jetzt ist alles wieder in Ordnung.
Nacho4d
4
@ nacho4d: Das ist seltsam, denn Git sollte nicht einmal wissen, dass es erweiterte Attribute gibt. Wenn Sie es reproduzieren könnten, wäre es wert, auf der Git-Mailingliste erwähnt zu werden. Wie es auf vger.kernel.orgListen üblich ist, müssen Sie keine Beiträge abonnieren (die Leute halten Sie für Antworten auf dem Laufenden) und sollten das ziemlich hohe Volumen der [email protected]Liste nicht berücksichtigen .
Jan Hudec

Antworten:

76

Es bedeutet einfach, dass wenn git den tatsächlichen Inhalt der Datei überprüft (es weiß nicht , dass eine bestimmte Erweiterung keine Binärdatei ist - Sie können die Attributdatei verwenden, wenn Sie dies explizit mitteilen möchten - siehe die Manpages).

Nachdem der Inhalt der Datei überprüft wurde, wurden Inhalte gefunden, die nicht in einfachen ASCII-Zeichen enthalten sind. Als UTF16 erwarte ich, dass es 'lustige' Charaktere haben wird, also denkt es, dass es binär ist.

Es gibt Möglichkeiten, git mitzuteilen, ob Sie Internationalisierung (i18n) oder erweiterte Zeichenformate für die Datei haben. Ich bin nicht genau genug über die genaue Methode, um das einzustellen - möglicherweise müssen Sie RT [Full] M ;-)

Bearbeiten: Eine schnelle Suche nach SO gefunden kann-i-make-git-erkennen-eine-utf-16-Datei-als-Text, die Ihnen ein paar Hinweise geben sollte.

Philip Oakley
quelle
10
Sie liegen fast aber nicht ganz falsch. Git hat die eigentlichen Dateien überprüft und dort "lustige" Charaktere gesehen. Es "glaubt" jedoch nicht, dass UTF-16 binär ist. Es ist binär, da Text als ASCII-basiert definiert ist (das ist das einzige, wofür das integrierte Diff brauchbare Ergebnisse liefert) und UTF-16 nicht. Ja, es gibt eine Möglichkeit, git anzuweisen, ein spezielles Diff für musterdefinierte Dateien zu verwenden (using .gitattributes).
Jan Hudec
2
Ich sollte hinzufügen, dass "lustige Zeichen" wirklich null Bytes bedeuten.
Jan Hudec
4
Wir haben beide Recht, aber aus unterschiedlichen Perspektiven. Wir sagen beide: "Git überprüft den Inhalt, um seinen Typ zu bestimmen." Wir beide sagen, dass, um Git wissen zu lassen, dass es als UTF16 behandelt werden sollte, der Benutzer Git über .gitattributesetc. mitteilen muss
Philip Oakley
7
@ JanHudec: Aus Ihrer Sicht sind ALLE Dateien binär.
Stolsvik
2
@stolosvik, (und JanH) Es ist ein subtilerer Mittelweg, dass UTF-8 sowohl die Basis-ASCII-Zeichen 0-127 als auch alle anderen Unicode-Zeichen enthält, ohne dass ein Nullbyte (00h) für etwas anderes als das Nullzeichen erforderlich ist (der 'C'-String-Terminator). Daher lautet die Textdefinition von Git, dass der Inhalt (also die ersten 1 KB) kein Null-Byte haben sollte, wenn utf-8 codiert wird. Versuchen Sie es mit stackoverflow.com/questions/2241348/…, um Spaß beim Lesen zu haben. Mein ursprünglicher Kommentar bezieht sich auf den Fall, dass UTF-16-codierte Daten als Bytepaare betrachtet werden, sodass das High-Byte für ASCII-Codepunkte 00 ist.
Philip Oakley
41

Wenn Sie den Dateityp nicht festgelegt haben, versucht Git, ihn automatisch zu ermitteln, und eine Datei mit sehr langen Zeilen und möglicherweise einigen breiten Zeichen (z. B. Unicode) wird als binär behandelt. Mit der .gitattributes- Datei können Sie definieren, wie Git die Datei interpretiert. Durch manuelles Festlegen des Diff- Attributs kann Git den Dateiinhalt als Text interpretieren und einen normalen Diff ausführen.

Fügen Sie einfach ein .gitattributes zu Ihrem Repository-Stammordner hinzu und setzen Sie das diff- Attribut auf die Pfade oder Dateien. Hier ist ein Beispiel:

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

Wenn Sie überprüfen möchten, ob für eine Datei Attribute festgelegt sind, können Sie dies mithilfe von git check-attr tun

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

Eine weitere nette Referenz zu Git-Attributen finden Sie hier .

naitsirch
quelle
1
Dies war hilfreich, ist aber tatsächlich falsch - das richtige Attribut ist es diffnicht text. Das textAttribut weist git nicht an, sich mithilfe von Text zu unterscheiden, sondern steuert stattdessen, wie Zeilenenden behandelt werden (Normalisierung auf LF). Weitere Informationen finden Sie unter Ihrem Link zu .gitattributes.
ErikE
Danke @ErikE. Ich habe meinen Beitrag gemäß Ihrem Kommentar und der Git-Dokumentation aktualisiert.
Naitsirch
4
Außerdem können Sie festlegen, welche Art von Diff ausgeführt werden soll. Wenn es sich beispielsweise um eine XML-Datei handelt, können Sie diese diff=xmlanstelle von nur verwenden diff.
Sandy Chapman
1
Was ist das Gegenteil von check-attr - gibt es ein set-attr? Ich habe ursprünglich versehentlich eine Datei als UTF-16 gespeichert, dann festgeschrieben und gepusht, und jetzt sieht BitBucket sie als UTF-16, auch nachdem ich sie erneut als UTF-8 gespeichert, festgeschrieben und erneut gepusht habe. Dies macht es grundsätzlich unmöglich, meine Pull-Anfragen zu lesen, da Prüfer in jeden einzelnen Kommentar klicken müssen, um Bewertungskommentare hinzuzufügen.
John Zabroski
21

Ich hatte dieses Problem, bei dem Git GUI und SourceTree Java / JS-Dateien als binär behandelten und daher keinen Unterschied feststellen konnten

Das Erstellen einer Datei mit dem Namen "Attribute" im Ordner ".git \ info" mit folgendem Inhalt hat das Problem behoben

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

Wenn Sie diese Änderung für alle Repositorys vornehmen möchten, können Sie die Attributdatei an folgendem Speicherort hinzufügen: $ HOME / .config / git / Attribute

Hemant
quelle
1
Beachten Sie auch die <project-root>/.gitattributesDatei, die die Änderung für alle Mitwirkenden und nur für das betreffende Projekt aktiviert.
Jpaugh
Das Hinzufügen * diffwar für mich hilfreich: Es zeigt den Unterschied bei allen Dateitypen. Ihre Lösung ist jedoch besser, da vermieden wird, dass in großen Binärdateien unnötige Unterschiede angezeigt werden.
Boolean_Type
Ja! Das hilft!
WildCat
19

Git wird sogar feststellen, dass es binär ist, wenn Sie eine superlange Zeile in Ihrer Textdatei haben. Ich habe einen langen String aufgelöst und ihn in mehrere Quellcodezeilen umgewandelt, und plötzlich wurde die Datei von 'binär' zu einer Textdatei, die ich sehen konnte (in SmartGit).

Geben Sie also nicht zu weit rechts ein, ohne in Ihrem Editor die Eingabetaste zu drücken. Andernfalls wird Git später glauben, Sie hätten eine Binärdatei erstellt.

Chris Murphy
quelle
1
Dies ist eine korrekte Information. Ich habe versucht, Unterschiede zu einem extrem großen MySQL-Dump (.sql-Datei) zu steuern, aber git behandelt ihn als Binärdatei, selbst wenn er nur ASCII / UTF8-Daten enthält. Der Grund dafür ist, dass die Zeilen sehr lang sind (Werte (eins), (zwei), (drei), (...), (3 Millionen ...) einfügen. Seltsamerweise tut dies das Git-Repository für jedes Commit nicht um 1,7 GB erhöhen, sondern nur ~ 350 MB. Vielleicht komprimiert Git die "binäre" Datei, bevor sie gespeichert wird.
Alexandre T.
@AlexandreT. Git komprimiert tatsächlich Datei-Blobs (mit GZip, IIRC).
Jpaugh
11

Ich hatte das gleiche Problem, nachdem ich eine meiner Dateien in einem neuen Editor bearbeitet hatte. Es stellte sich heraus, dass der neue Editor eine andere Codierung (Unicode) als mein alter Editor (UTF-8) verwendete. Also habe ich meinem neuen Editor einfach gesagt, dass er meine Dateien mit UTF-8 speichern soll, und dann hat git meine Änderungen wieder richtig angezeigt und es nicht als Binärdatei angesehen.

Ich denke, das Problem war einfach, dass Git nicht weiß, wie man Dateien mit verschiedenen Codierungstypen vergleicht. Der von Ihnen verwendete Codierungstyp spielt also keine Rolle, solange er konsistent bleibt.

Ich habe es nicht getestet, aber ich bin mir sicher, wenn ich meine Datei nur mit der neuen Unicode-Codierung festgeschrieben hätte. Wenn ich das nächste Mal Änderungen an dieser Datei vorgenommen hätte, hätte sie die Änderungen korrekt angezeigt und sie seitdem nicht als binär erkannt Dann hätte es zwei Unicode-codierte Dateien und keine UTF-8-Datei mit einer Unicode-Datei verglichen.

Sie können eine App wie Notepad ++ verwenden , um den Codierungstyp einer Textdatei einfach anzuzeigen und zu ändern. Öffnen Sie die Datei in Notepad ++ und verwenden Sie das Menü Codierung in der Symbolleiste.

tödlicher Hund
quelle
1
Unicode ist keine Codierung. Es ist ein Zeichensatz und UTF-8 ist eine seiner Codierungen, dh die Möglichkeit, einen Unicode-Codepunkt zu codieren
phuclv
1
Dies löst das Problem nicht, sondern vermeidet es nur. Das Problem ist, dass git oder sein diff-Tool Textdateien nicht richtig erkennt oder es dem Benutzer nicht leicht ermöglicht, sein Verhalten zu überschreiben.
Preza8
6

Ich habe das gleiche Problem gehabt. Ich habe den Thread gefunden, als ich nach einer Lösung auf Google gesucht habe, aber ich finde immer noch keinen Hinweis. Aber ich denke, ich habe den Grund nach dem Studium gefunden. Das folgende Beispiel wird meinen Hinweis klar erklären.

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

Derzeit wird die Datei new.txt als Textdatei betrachtet.

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

Sie erhalten dieses Ergebnis

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

und versuche das

git diff -a

Sie werden unten bekommen

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

Wir hatten diesen Fall, in dem eine HTML-Datei als binär angesehen wurde, wenn wir versuchten, Änderungen daran vorzunehmen. Sehr uncool, um keine Unterschiede zu sehen. Um ehrlich zu sein, habe ich hier nicht alle Lösungen überprüft, aber für uns hat Folgendes funktioniert:

  1. Die Datei wurde entfernt (tatsächlich auf meinen Desktop verschoben) und die Datei festgeschrieben git deletion. Git sagtDeleted file with mode 100644 (Regular) Binary file differs
  2. Fügte die Datei erneut hinzu (verschob sie tatsächlich von meinem Desktop zurück in das Projekt). Git sagt, dass New file with mode 100644 (Regular) 1 chunk, 135 insertions, 0 deletionsdie Datei jetzt als normale Textdatei hinzugefügt wird

Von nun an werden alle Änderungen, die ich an der Datei vorgenommen habe, als regulärer Textunterschied angesehen. Sie können diese Commits auch unterdrücken (1, 2 und 3 sind die tatsächlichen Änderungen, die Sie vornehmen), aber ich möchte in Zukunft lieber sehen, was ich getan habe. Squashing 1 & 2 zeigt eine binäre Änderung.

StuFF mc
quelle
Ähnlich verhält es sich mit einer oder zwei (erfolgreich kompilierten) CPP-Dateien, die von VS hochgeschoben wurden. Macht die Github-GUI für Compare lächerlich. Man möchte in einem solchen Ding-Dong-Austausch keine Fliege auf der Glocke sein - VS auf der einen Seite sagt, es sei Github, und auf der anderen Seite sagt Github, es sei VS. :(
Laurie Stearn
4

Anhand dieser hilfreichen Antwort können Sie Git direkt fragen, warum eine Datei auf bestimmte Weise behandelt wird:

cd directory/of/interest
file *

Es erzeugt eine nützliche Ausgabe wie folgt:

$ 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
patricktokeeffe
quelle
6
fileist kein Git-Befehl. Es ist ein völlig separates Tool, das unter Windows mit Git gepackt ist. Gibt es eine Dokumentation, die zeigt, dass Git dies für die Erkennung von Binärdateien verwendet?
Max
4

Dies wird auch (zumindest unter Windows) durch Textdateien mit UTF-8 mit Stücklistencodierung verursacht . Durch Ändern der Codierung in reguläres UTF-8 wurde Git die Datei sofort als Typ = Text angezeigt

Robba
quelle
1

Ich hatte eine Instanz, in der absichtlich .gitignoreeine Doppelsequenz \r(Wagenrücklauf) enthalten war.

Diese Datei wurde von git als binär identifiziert. Das Hinzufügen einer .gitattributesDatei hat geholfen.

# .gitattributes file
.gitignore diff
Erik Zivkovic
quelle
1
Hat funktioniert. Ich hatte auch ein doppeltes \ r, um einige OS "Icon \ r \ r" -Dateien zu ignorieren. Gut, die Ursache sowie die Lösung zu kennen.
Hsandt
1

Wenn git check-attr --all -- src/my_file.txtIhre Datei als binär gekennzeichnet ist und Sie sie nicht als binär festgelegt haben .gitattributes, überprüfen Sie sie /.git/info/attributes.

coberlin
quelle
0

Ändern Sie die Datei Aux.js in einen anderen Namen, z. B. Sig.js.

Der Quellbaum zeigt es weiterhin als Binärdatei an, aber Sie können es bereitstellen (hinzufügen) und festschreiben.

Oscar Zhou1989
quelle
0

Ich hatte ein ähnliches Problem, als ich Text aus einer binären Kafka-Nachricht einfügte, die ein nicht sichtbares Zeichen einfügte und git veranlasste, die Datei für binär zu halten.

Ich habe die beleidigenden Zeichen gefunden, indem ich die Datei mit Regex durchsucht habe [^ -~\n\r\t]+.

  • [ Übereinstimmende Zeichen in diesem Satz
  • ^ Übereinstimmungszeichen, die nicht in diesem Satz enthalten sind
  • -~ stimmt mit allen Zeichen von '' (Leerzeichen) bis '~' überein.
  • \n Neue Zeile
  • \r Wagenrücklauf
  • \t Tab
  • ] Set schließen
  • + stimmen mit einem oder mehreren dieser Zeichen überein
Martyn Davis
quelle
-2

Ich habe nur einige Stunden damit verbracht, alles auf dieser Liste durchzugehen, um herauszufinden, warum eines der Testprojekte in meiner Lösung dem Explorer keine Tests hinzufügte.

In meinem Fall stellte sich heraus, dass VS (wahrscheinlich aufgrund einer schlechten Git-Zusammenführung irgendwo) irgendwie eine Referenz für das Projekt verloren hatte. Es wurde noch gebaut, aber ich bemerkte, dass es nur die Abhängigkeiten baute.

Ich bemerkte dann, dass es nicht in der Abhängigkeitsliste selbst angezeigt wurde, also entfernte ich das Testprojekt und fügte es erneut hinzu, und alle meine Tests wurden schließlich angezeigt.

Cirrus
quelle
2
Visual Studio ist hier wirklich nicht relevant.
Jpaugh