Posso far riconoscere a git un file UTF-16 come testo?

Sto monitorando un file della macchina virtuale Virtual PC (* .vmc) in git, e dopo aver apportato una modifica git ha identificato il file come binario e non lo avrebbe diff per me. Ho scoperto che il file era codificato in UTF-16.

Si può insegnare a riconoscere che questo file è testo e gestirlo in modo appropriato?

Sto usando git sotto Cygwin, con core.autocrlf impostato su false. Potrei usare mSysGit o git sotto UNIX, se necessario.

Ho lottato con questo problema per un po ‘e ho appena scoperto (per me) una soluzione perfetta:

$ git config --global diff.tool vimdiff # or merge.tool to get merging too! $ git difftool commit1 commit2 

git difftool accetta gli stessi argomenti di git diff , ma esegue un programma diff di tua scelta al posto del diff integrato GNU. Quindi scegli un diff multibyte-aware (nel mio caso, vim in modalità diff) e usa semplicemente git difftool invece di git diff .

Trova “difftool” troppo lungo per digitare? Nessun problema:

 $ git config --global alias.dt difftool $ git dt commit1 commit2 

Scatenati.

C’è una soluzione molto semplice che funziona fuori dagli schemi di Unices.

Ad esempio, con i file .strings di Apple:

  1. Crea un file .gitattributes nella root del tuo repository con:

     *.strings diff=localizablestrings 
  2. Aggiungi quanto segue al tuo file ~/.gitconfig :

     [diff "localizablestrings"] textconv = "iconv -f utf-16 -t utf-8" 

Fonte: file .strings in Git (e post precedente dal 2010).

Hai provato a impostare il tuo .gitattributes per trattarlo come un file di testo?

per esempio:

 *.vmc diff 

Maggiori dettagli su http://www.git-scm.com/docs/gitattributes.html .

Di default, sembra che git non funzioni bene con UTF-16; per questo tipo di file devi assicurarti che nessuna elaborazione CRLF sia fatta su di essa, ma tu vuoi diff e merge per funzionare come un normale file di testo (questo è ignorare se il tuo terminale / editor può gestire UTF-16).

Ma guardando la pagina di .gitattributes , ecco l’attributo personalizzato che è binary :

 [attr]binary -diff -crlf 

Quindi mi sembra che tu possa definire un attributo personalizzato nel tuo livello più alto .gitattributes per utf16 (nota che aggiungo merge qui per essere sicuro che sia trattato come testo):

 [attr]utf16 diff merge -crlf 

Da lì saresti in grado di specificare in qualsiasi file .gitattributes qualcosa come:

 *.vmc utf16 

Nota inoltre che dovresti essere ancora in grado di diff un file, anche se git pensa che sia binario con:

 git diff --text 

modificare

Questa risposta dice fondamentalmente che il diff di GNU con UTF-16 o anche UTF-8 non funziona molto bene. Se vuoi che git usi uno strumento diverso per vedere le differenze (tramite --ext-diff ), quella risposta suggerisce Guiffy .

Ma probabilmente è necessario diff un file UTF-16 che contiene solo caratteri ASCII. Un modo per farlo funzionare è usare --ext-diff e il seguente script di shell:

 #!/bin/bash diff <(iconv -f utf-16 -t utf-8 "$1") <(iconv -f utf-16 -t utf-8 "$2") 

Nota che la conversione in UTF-8 potrebbe funzionare anche per la fusione, devi solo assicurarti che sia fatta in entrambe le direzioni.

Per quanto riguarda l'output al terminale quando si guarda un diff di un file UTF-16:

Cercando di diff come quello risulta nella spazzatura binaria vomitata sullo schermo. Se git usa GNU diff, sembrerebbe che GNU diff non sia sensibile all'unicode.

GNU diff non si preoccupa davvero di unicode, quindi quando si usa diff --text lo si diffonde e si diffonde il testo. Il problema è che il terminale che stai utilizzando non può gestire l'UTF-16 emesso (combinato con i segni di diff che sono caratteri ASCII).

La soluzione è filtrare attraverso cmd.exe /c "type %1" . il built-in del type di cmd farà la conversione, e quindi puoi usarlo con l’abilità textconv di git diff per abilitare la diffusione del testo dei file UTF-16 (dovrebbe funzionare anche con UTF-8, sebbene non testato).

Citando dalla pagina man di gitattributes:


Esecuzione di diffs di testo di file binari

A volte è preferibile vedere il diff di una versione convertita da testo di alcuni file binari. Ad esempio, un documento di elaboratore di testi può essere convertito in una rappresentazione di testo ASCII e il diff del testo mostrato. Anche se questa conversione perde alcune informazioni, la differenza risultante è utile per la visualizzazione umana (ma non può essere applicata direttamente).

L’opzione di configurazione textconv viene utilizzata per definire un programma per l’esecuzione di tale conversione. Il programma dovrebbe prendere un singolo argomento, il nome di un file da convertire e produrre il testo risultante su stdout.

Ad esempio, per mostrare la differenza delle informazioni exif di un file invece delle informazioni binarie (supponendo che lo strumento exif sia installato), aggiungi la seguente sezione al tuo $GIT_DIR/config file di $GIT_DIR/config (o $HOME/.gitconfig file):

 [diff "jpg"] textconv = exif 

Una soluzione per mingw32 , i fan di cygwin potrebbero dover modificare l’approccio. Il problema è con il passare il nome del file da convertire in cmd.exe – userà le barre in avanti e cmd assume i separatori delle directory backslash.

Passo 1:

Crea lo script a singolo argomento che eseguirà la conversione in stdout. c: \ percorso \ to \ qualche \ script.sh:

 #!/bin/bash SED='s/\//\\\\\\\\/g' FILE=\`echo $1 | sed -e "$SED"\` cmd.exe /c "type $FILE" 

Passo 2:

Configura git per poter utilizzare il file di script. All’interno del tuo git config ( ~/.gitconfig o .git/config o vedi man git-config ), inserisci questo:

 [diff "cmdtype"] textconv = c:/path/to/some/script.sh 

Passaggio 3:

Indica i file per applicare questo workarond utilizzando i file .gitattributes (vedi man gitattributes (5)):

 *vmc diff=cmdtype 

quindi usa git diff sui tuoi file.

Ho scritto un piccolo driver git-diff, to-utf8 , che dovrebbe facilitare la diffusione di qualsiasi file codificato non ASCII / UTF-8. Puoi installarlo seguendo le istruzioni qui: https://github.com/chaitanyagupta/gitutils#to-utf8 (lo script to-utf8 è disponibile nello stesso repository).

Si noti che questo script richiede che sia file comandi file che iconv siano disponibili sul sistema.

Ha avuto questo problema su Windows di recente, e i dos2unix e unix2dos forniti con git for windows hanno fatto il trucco. Per impostazione predefinita si trovano in C:\Program Files\Git\usr\bin\ . Osserva che funzionerà solo se il tuo file non ha bisogno di essere UTF-16. Ad esempio, qualcuno ha accidentalmente codificato un file python come UTF-16 quando non era necessario (nel mio caso).

 PS C:\Users\xxx> dos2unix my_file.py dos2unix: converting UTF-16LE file my_file.py to ANSI_X3.4-1968 Unix format... 

e

 PS C:\Users\xxx> unix2dos my_file.py unix2dos: converting UTF-16LE file my_file.py to ANSI_X3.4-1968 DOS format...