Je suis en train de suivre un fichier de machine virtuelle Virtual PC (* .vmc) dans git, et après avoir effectué une modification, git a identifié le fichier comme binaire et ne le différerait pas pour moi. J'ai découvert que le fichier était encodé en UTF-16.
Peut-on apprendre à git à reconnaître que ce fichier est du texte et à le gérer correctement?
J'utilise git sous Cygwin, avec core.autocrlf défini sur false. Je pourrais utiliser mSysGit ou git sous UNIX, si nécessaire.
Je lutte avec ce problème depuis un certain temps et je viens de découvrir (pour moi) une solution parfaite:
$ git config --global diff.tool vimdiff # or merge.tool to get merging too!
$ git difftool commit1 commit2
git difftool
prend les mêmes arguments que git diff
le ferait, mais exécute un programme de diff de votre choix au lieu du programme intégré GNU diff
. Choisissez donc un diff compatible multi-octets (dans mon cas, vim
en mode diff) et utilisez simplement git difftool
au lieu de git diff
.
Vous trouvez "difftool" trop long pour taper? Aucun problème:
$ git config --global alias.dt difftool
$ git dt commit1 commit2
Git rocks.
Il existe une solution très simple qui fonctionne par défaut sur Unices.
Par exemple, avec les fichiers .strings
D'Apple:
Créez un fichier .gitattributes
À la racine de votre référentiel avec:
*.strings diff=localizablestrings
Ajoutez ce qui suit à votre fichier ~/.gitconfig
:
[diff "localizablestrings"]
textconv = "iconv -f utf-16 -t utf-8"
Source: fichiers Diff .strings dans Git (et ancien article de 2010).
Avez-vous essayé de définir votre .gitattributes
pour le traiter comme un fichier texte?
par exemple.:
*.vmc diff
Plus de détails sur http://www.git-scm.com/docs/gitattributes.html .
Par défaut, il semble que git
ne fonctionne pas bien avec UTF-16; pour un tel fichier, vous devez vous assurer qu'aucun traitement CRLF
n'est effectué dessus, mais vous voulez que diff
et merge
fonctionnent comme un fichier texte normal (ceci ignore si votre terminal/éditeur peut gérer UTF-16).
Mais en regardant le .gitattributes
manpage , voici l'attribut personnalisé qui est binary
:
[attr]binary -diff -crlf
Il me semble donc que vous pourriez définir un attribut personnalisé dans votre niveau supérieur .gitattributes
pour utf16
(notez que j'ajoute fusion ici pour être sûr qu'il est traité comme du texte):
[attr]utf16 diff merge -crlf
De là, vous seriez en mesure de spécifier dans n'importe quel .gitattributes
fichier quelque chose comme:
*.vmc utf16
Notez également que vous devriez toujours pouvoir diff
un fichier, même si git
pense que c'est binaire avec:
git diff --text
Modifier
Cette réponse dit essentiellement que GNU diff wth UTF-16 ou même UTF-8 ne fonctionne pas très bien. Si vous voulez avoir git
utilisez un autre outil pour voir les différences (via --ext-diff
), cette réponse suggère Guiffy .
Mais ce dont vous avez probablement besoin est simplement de diff
un fichier UTF-16 qui ne contient que ASCII caractères. Une façon de faire fonctionner cela est d'utiliser --ext-diff
et le script Shell suivant:
#!/bin/bash
diff <(iconv -f utf-16 -t utf-8 "$1") <(iconv -f utf-16 -t utf-8 "$2")
Notez que la conversion en UTF-8 peut également fonctionner pour la fusion, il vous suffit de vous assurer que cela se fait dans les deux sens.
Quant à la sortie vers le terminal en regardant un diff d'un fichier UTF-16:
Essayer de faire une différence comme cela entraîne des ordures binaires crachées à l'écran. Si git utilise GNU diff, il semblerait que GNU diff ne soit pas compatible Unicode).
GNU diff ne se soucie pas vraiment de l'unicode, donc lorsque vous utilisez diff --text, il diffère juste et produit le texte. Le problème est que le terminal que vous utilisez ne peut pas gérer l'UTF-16 qui est émis (combiné avec les marques de diff ASCII caractères).
La solution consiste à filtrer à travers cmd.exe /c "type %1"
. La commande intégrée type
de cmd effectuera la conversion, et vous pouvez donc l'utiliser avec la capacité textconv de git diff pour activer la différence de texte des fichiers UTF-16 (devrait également fonctionner avec UTF-8, bien que non testé).
Citant la page de manuel de gitattributes:
Parfois, il est souhaitable de voir la différence d'une version convertie en texte de certains fichiers binaires. Par exemple, un document de traitement de texte peut être converti en une représentation textuelle ASCII et le diff du texte affiché. Même si cette conversion perd certaines informations, le diff résultant est utile pour la visualisation humaine ( mais ne peut pas être appliqué directement).
L'option de configuration textconv est utilisée pour définir un programme pour effectuer une telle conversion. Le programme doit prendre un seul argument, le nom d'un fichier à convertir, et produire le texte résultant sur stdout.
Par exemple, pour afficher la différence des informations exif d'un fichier au lieu des informations binaires (en supposant que l'outil exif est installé), ajoutez la section suivante à votre $GIT_DIR/config
fichier (ou $HOME/.gitconfig
fichier):
[diff "jpg"]
textconv = exif
Une solution pour mingw32, les fans de cygwin devront peut-être modifier l'approche. Le problème est de passer le nom de fichier à convertir en cmd.exe - il utilisera des barres obliques et cmd suppose des séparateurs de répertoires de barre oblique inverse.
Créez le script à argument unique qui effectuera la conversion en stdout. c:\chemin\vers\certains\script.sh:
#!/bin/bash
SED='s/\//\\\\\\\\/g'
FILE=\`echo $1 | sed -e "$SED"\`
cmd.exe /c "type $FILE"
Configurez git pour pouvoir utiliser le fichier de script. Dans votre configuration git (~/.gitconfig
ou .git/config
ou voir man git-config
), mettez ceci:
[diff "cmdtype"]
textconv = c:/path/to/some/script.sh
Indiquez les fichiers auxquels appliquer cette solution de contournement en utilisant des fichiers .gitattributes (voir man gitattributes (5)):
*vmc diff=cmdtype
puis utilisez git diff
sur vos fichiers.
J'ai écrit un petit pilote git-diff, to-utf8
, ce qui devrait faciliter la différenciation de tous les fichiers encodés non ASCII/UTF-8. Vous pouvez l'installer en utilisant les instructions ici: https://github.com/chaitanyagupta/gitutils#to-utf8 (le to-utf8
le script est disponible dans le même dépôt).
Notez que ce script requiert que les commandes file
et iconv
soient disponibles sur le système.
git a récemment commencé à comprendre des encodages tels que utf16. Voir gitattributes docs, recherchez working-tree-encoding
[Assurez-vous que votre page de manuel correspond, car c'est assez nouveau!]
Si (par exemple) le fichier est utf-16 sans bom sur la machine Windows, ajoutez-le à votre fichier gitattributes
*.vmc text working-tree-encoding=UTF-16LE eol=CRLF
Si utf-16 (avec bom) sur * nix, faites-le
*.vmc text working-tree-encoding=UTF-16 eol=LF
J'ai rencontré récemment ce problème sous Windows et le dos2unix
et unix2dos
les bacs livrés avec git pour windows ont fait l'affaire. Par défaut, ils sont situés dans C:\Program Files\Git\usr\bin\
. Notez que cela ne fonctionnera que si votre fichier n'a pas besoin d'être UTF-16. Par exemple, quelqu'un a accidentellement encodé un python au format UTF-16 alors qu'il n'était pas nécessaire de le faire (dans mon cas).
PS C:\Users\xxx> dos2unix my_file.py
dos2unix: converting UTF-16LE file my_file.py to ANSI_X3.4-1968 Unix format...
et
PS C:\Users\xxx> unix2dos my_file.py
unix2dos: converting UTF-16LE file my_file.py to ANSI_X3.4-1968 DOS format...