Pourquoi Git traite-t-il ce fichier texte comme un fichier binaire?

150

Je me demande pourquoi git me dit ceci:?

$ 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

Ne sont-ils pas des fichiers texte?

J'ai vérifié le .gitattributes et il est vide. Pourquoi je reçois ce message? Je ne peux plus avoir de diffs comme je le faisais

AJOUTÉE:

J'ai remarqué qu'il y a une @autorisation dans le fichier, qu'est-ce que c'est? Serait-ce la raison?

$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
la source
4
Il peut s'agir d'un fichier encodé en UTF-8.
Marnix van Valen
Il est censé être UTF16 little endian LF
nacho4d
1
Depuis la lspage de manuel sous Mac OS X: Si le fichier ou le répertoire possède des attributs étendus, le champ des autorisations imprimé par l' -loption est suivi d'un @caractère . Utilisez l'option -@pour voir ces attributs étendus.
adl du
Je pense que cela pourrait être un bug de git. J'ai supprimé les attributs étendus et maintenant tout va bien à nouveau.
nacho4d
4
@ nacho4d: C'est étrange, car git ne devrait même pas savoir qu'il existe des attributs étendus. Si vous pouviez le reproduire, cela vaudrait la peine de figurer sur la liste de diffusion git. Comme il est de coutume sur les vger.kernel.orglistes, vous n'êtes pas obligé de vous abonner pour publier (les gens vous garderont CC pour les réponses) et sont en quelque sorte censés ne pas être compte tenu du volume assez élevé de la [email protected]liste.
Jan Hudec

Réponses:

76

Cela signifie simplement que lorsque git inspecte le contenu réel du fichier (il ne sait pas qu'une extension donnée n'est pas un fichier binaire - vous pouvez utiliser le fichier d'attributs si vous voulez le dire explicitement - voir les pages de manuel).

Après avoir inspecté le contenu du fichier, il a vu des éléments qui ne sont pas en caractères ascii de base. Étant UTF16, je m'attends à ce qu'il ait des caractères «drôles», donc il pense que c'est binaire.

Il existe des moyens de dire à git si vous avez des formats d'internationalisation (i18n) ou de caractères étendus pour le fichier. Je ne suis pas suffisamment au fait de la méthode exacte pour définir cela - vous devrez peut-être RT [Full] M ;-)

Edit: une recherche rapide de SO a trouvé can-i-make-git-Recogn-a-utf-16-file-as-text qui devrait vous donner quelques indices.

Philip Oakley
la source
10
Vous avez presque mais pas complètement tort. Git a inspecté les fichiers réels et y a vu des personnages «amusants». Cependant, il ne "pense" pas que l'UTF-16 est binaire. Il est binaire, car le texte est défini comme basé sur ASCII (c'est la seule chose pour laquelle le diff intégré donnera des résultats utilisables) et UTF-16 ne l'est pas. Oui, il existe un moyen de dire à git d'utiliser une différence spéciale pour les fichiers définis par des motifs (en utilisant .gitattributes).
Jan Hudec
2
Je devrais ajouter que «caractères drôles» signifie vraiment zéro octet.
Jan Hudec
4
Nous avons tous les deux raison, mais sous des angles différents. Nous disons tous les deux "Git inspecte le contenu pour déterminer son type". Nous disons tous les deux que pour faire savoir à git qu'il doit être traité comme UTF16, l'utilisateur doit le dire via .gitattributesetc.
Philip Oakley
7
@JanHudec: À votre avis, TOUS les fichiers sont binaires.
stolsvik
2
@stolosvik, (et JanH) C'est un terrain d'entente plus subtil en ce que UTF-8 comprend à la fois les caractères ASCII de base 0-127 et tous les autres caractères Unicode, sans avoir besoin d'un octet nul (00h) pour autre chose que le caractère nul (le terminateur de chaîne «C»). Ainsi, la définition de texte de Git est que le contenu (enfin les 1k premiers octets) ne doit pas avoir d'octet nul lorsqu'il est encodé en utf-8. Essayez stackoverflow.com/questions/2241348/… pour une lecture amusante. Mon commentaire original fait référence au cas où les données encodées en UTF-16 sont considérées comme des paires d'octets, donc l'octet de poids fort pour les points de code ascii sera 00.
Philip Oakley
41

Si vous n'avez pas défini le type d'un fichier, Git essaie de le déterminer automatiquement et un fichier avec de très longues lignes et peut-être des caractères larges (par exemple Unicode) est traité comme binaire. Avec le fichier .gitattributes , vous pouvez définir comment Git interprète le fichier. La définition manuelle de l'attribut diff permet à Git d'interpréter le contenu du fichier comme du texte et effectuera un diff habituel.

Ajoutez simplement un .gitattributes au dossier racine de votre référentiel et définissez l' attribut diff sur les chemins ou les fichiers. Voici un exemple:

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

Si vous voulez vérifier s'il y a des attributs définis sur un fichier, vous pouvez le faire à l'aide de git check-attr

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

Une autre référence intéressante sur les attributs Git peut être trouvée ici .

naitsirch
la source
1
Cela a été utile, mais est en fait incorrect - le bon attribut ne l'est diffpas text. L' textattribut ne dit pas à git de diff en utilisant du texte, mais contrôle à la place la manière dont les fins de ligne sont gérées (normalisation à LF). Voir votre lien vers .gitattributes pour plus de détails.
ErikE
Merci @ErikE. J'ai mis à jour mon message en fonction de votre commentaire et de la documentation Git.
naitsirch
4
En outre, vous pouvez définir le type de comparaison à effectuer. Par exemple, s'il s'agit d'un fichier xml, vous pouvez utiliser diff=xmlau lieu de simplement diff.
Sandy Chapman
1
Quel est le contraire de check-attr - y a-t-il un set-attr? Au départ, j'ai accidentellement enregistré un fichier au format UTF-16, puis je l'ai validé et poussé, et maintenant BitBucket le voit comme UTF-16, même après l'avoir réenregistré en UTF-8, en le validant et en le poussant à nouveau. Cela rend essentiellement mes demandes d'extraction impossibles à lire car les critiques doivent cliquer sur chaque commentaire individuel pour ajouter des commentaires.
John Zabroski
21

J'avais ce problème où Git GUI et SourceTree traitaient les fichiers Java / JS comme binaires et ne pouvaient donc pas voir la différence

La création d'un fichier nommé "attributs" dans le dossier .git \ info avec le contenu suivant a résolu le problème

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

Si vous souhaitez effectuer cette modification pour tous les référentiels, vous pouvez ajouter un fichier d'attributs à l'emplacement suivant $ HOME / .config / git / attributes

Hemant
la source
1
Notez également le <project-root>/.gitattributesfichier, qui rend la modification active pour tous les contributeurs, et uniquement pour le projet concerné.
jpaugh
L'ajout a * diffété utile pour moi: cela montre la différence dans tous les types de fichiers. Mais votre solution est meilleure, car vous évitez d'afficher les différences inutiles dans les gros fichiers binaires.
Boolean_Type
Ouais! CA aide!
WildCat
19

Git déterminera même qu'il s'agit d'un binaire si vous avez une très longue ligne dans votre fichier texte. J'ai brisé une longue chaîne, la transformant en plusieurs lignes de code source, et tout à coup le fichier est passé du statut de «binaire» à un fichier texte que je pouvais voir (dans SmartGit).

Donc, ne continuez pas à taper trop à droite sans appuyer sur «Entrée» dans votre éditeur - sinon plus tard, Git pensera que vous avez créé un fichier binaire.

Chris Murphy
la source
1
C'est une information correcte. J'essayais de contrôler les différences vers un très grand MySQL Dump (fichier .sql), mais git le traite comme un fichier binaire, même s'il ne contient que des données ASCII / UTF8. La raison est que les lignes sont super longues (insérez les valeurs (un), (deux), (trois), (...), (3 millions ...);. Étrangement, pour chaque commit, le dépôt git fait pas augmenter de 1,7 Go, mais seulement ~ 350 Mo. Peut-être que git est en train de compresser le fichier "binaire" avant de le sauvegarder.
Alexandre T.
@AlexandreT. Git compresse en effet les blobs de fichiers (en utilisant GZip, IIRC).
jpaugh
11

J'ai eu ce même problème après avoir édité un de mes fichiers dans un nouvel éditeur. Il s'avère que le nouvel éditeur utilisait un encodage différent (Unicode) de mon ancien éditeur (UTF-8). J'ai donc simplement dit à mon nouvel éditeur de sauvegarder mes fichiers avec UTF-8, puis git a montré à nouveau mes modifications correctement et ne l'a pas vu comme un fichier binaire.

Je pense que le problème était simplement que git ne savait pas comment comparer des fichiers de différents types d'encodage. Ainsi, le type d'encodage que vous utilisez n'a pas vraiment d'importance, tant qu'il reste cohérent.

Je ne l'ai pas testé, mais je suis sûr que si je venais de valider mon fichier avec le nouvel encodage Unicode, la prochaine fois que j'apporterais des modifications à ce fichier, il aurait montré les modifications correctement et ne les aurait pas détectées comme binaire, car alors il aurait comparé deux fichiers encodés Unicode, et non un fichier UTF-8 à un fichier Unicode.

Vous pouvez utiliser une application comme Notepad ++ pour voir et modifier facilement le type d'encodage d'un fichier texte; Ouvrez le fichier dans Notepad ++ et utilisez le menu Encodage dans la barre d'outils.

chien mortel
la source
1
Unicode n'est pas un encodage. C'est un jeu de caractères et UTF-8 est l'un de ses encodages, c'est-à-dire le moyen d'encoder un codet Unicode
phuclv
1
Cela ne résout pas le problème, mais l'évite. Le problème est que git ou son outil diff ne reconnaît pas correctement les fichiers texte ou ne permet pas facilement à l'utilisateur de remplacer son comportement.
Preza8 le
6

J'ai eu le même problème. J'ai trouvé le fil de discussion lorsque je recherche une solution sur Google, mais je ne trouve toujours aucun indice. Mais je pense avoir trouvé la raison après avoir étudié, l'exemple ci-dessous expliquera clairement mon indice.

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

pour l'instant, le fichier new.txt est considéré comme un fichier texte.

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

vous obtiendrez ce résultat

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

et essayez ça

git diff -a

vous obtiendrez ci-dessous

    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
la source
5

Nous avons eu ce cas où un fichier .html était considéré comme binaire chaque fois que nous essayions d'y apporter des modifications. Très pas cool de ne pas voir les diffs. Pour être honnête, je n'ai pas vérifié toutes les solutions ici, mais ce qui a fonctionné pour nous était le suivant:

  1. Supprimé le fichier (en fait déplacé sur mon bureau) et validé le git deletion . Git ditDeleted file with mode 100644 (Regular) Binary file differs
  2. Re-ajouté le fichier (en fait déplacé de mon bureau dans le projet). Git dit que New file with mode 100644 (Regular) 1 chunk, 135 insertions, 0 deletionsle fichier est maintenant ajouté en tant que fichier texte normal

À partir de maintenant, toutes les modifications que j'ai apportées au fichier sont considérées comme un diff de texte normal. Vous pouvez également écraser ces commits (1, 2 et 3 étant le changement réel que vous apportez) mais je préfère pouvoir voir à l'avenir ce que j'ai fait. Écraser 1 et 2 affichera un changement binaire.

StuFF mc
la source
Similaire avec un ou deux fichiers cpp (compilés avec succès) poussés depuis VS. Rend l'interface graphique Github pour Compare ridicule. On ne voudrait pas être une mouche sur la cloche dans un tel échange de ding dong, - VS d'un côté en disant que c'est Github, et de l'autre côté Github en disant que c'est VS. :(
Laurie Stearn
4

Selon cette réponse utile , vous pouvez demander directement à Git pourquoi il traite un fichier d'une manière particulière:

cd directory/of/interest
file *

Il produit une sortie utile comme celle-ci:

$ 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
la source
6
filen'est pas une commande git. C'est un outil totalement séparé fourni avec git sur Windows. Existe-t-il une documentation montrant que c'est ce que git utilise pour la détection de fichiers binaires?
Max
4

Cela est également causé (au moins sous Windows) par des fichiers texte qui ont UTF-8 avec encodage BOM . En changeant l'encodage en UTF-8 normal, Git voit immédiatement le fichier comme type = text

Robba
la source
1

J'ai eu une instance où .gitignorecontenait un double\r séquence (retour chariot) par but.

Ce fichier a été identifié comme binaire par git. L'ajout d'un .gitattributesfichier a aidé.

# .gitattributes file
.gitignore diff
Erik Zivkovic
la source
1
Travaillé. J'ai également eu un double \ r pour ignorer certains fichiers "Icon \ r \ r" du système d'exploitation. Il est bon de connaître la cause ainsi que le correctif.
hsandt
1

Si cela git check-attr --all -- src/my_file.txtindique que votre fichier est marqué comme binaire et que vous ne l'avez pas défini comme binaire dans .gitattributes, vérifiez-le /.git/info/attributes.

Coberlin
la source
0

Remplacez Aux.js par un autre nom, comme Sig.js.

L'arborescence source l'affiche toujours sous forme de fichier binaire, mais vous pouvez la mettre en scène (l'ajouter) et la valider.

Oscar Zhou1989
la source
0

J'ai eu un problème similaire en collant du texte à partir d'un message binaire Kafka, qui insérait un caractère non visible et faisait croire à git que le fichier était binaire.

J'ai trouvé les caractères incriminés en recherchant le fichier à l'aide de regex [^ -~\n\r\t]+.

  • [ faire correspondre les caractères de cet ensemble
  • ^ correspond à des caractères n'appartenant pas à cet ensemble
  • -~ correspond à tous les caractères de '' (espace) à '~'
  • \n nouvelle ligne
  • \r retour chariot
  • \t languette
  • ] fermer l'ensemble
  • + correspond à un ou plusieurs de ces caractères
Martyn Davis
la source
-2

Je viens de passer plusieurs heures à parcourir tout ce qui figure sur cette liste à essayer de comprendre pourquoi l'un des projets de test de ma solution n'ajoutait aucun test à l'explorateur.

Il s'est avéré dans mon cas que d'une manière ou d'une autre (probablement en raison d'une mauvaise fusion git quelque part) que VS avait complètement perdu une référence au projet. Il était encore en construction mais j'ai remarqué qu'il ne construisait que les dépendances.

J'ai ensuite remarqué qu'il n'apparaissait pas dans la liste des dépendances elle-même, alors j'ai supprimé et rajouté le projet de test et tous mes tests sont finalement apparus.

cirrus
la source
2
Visual Studio n'est vraiment pas pertinent ici.
jpaugh