gitにUTF-16ファイルをテキストとして認識させることはできますか?


140

Virtual PC仮想マシンファイル(* .vmc)をgitで追跡していますが、変更を加えた後、gitはファイルをバイナリとして識別し、差分を表示しません。ファイルがUTF-16でエンコードされていることを発見しました。

このファイルがテキストであることを認識し、適切に処理するようにgitを教えることができますか?

Cygwinでgitを使用していますが、core.autocrlfをfalseに設定しています。必要に応じて、UNIXでmSysGitまたはgitを使用できます。

回答:


83

私はこの問題にしばらく取り組んでいますが、(私にとって)完璧な解決策を見つけました:

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

git difftoolと同じ引数を取りgit diffますが、組み込みのGNUではなく、選択したdiffプログラムを実行しますdiff。したがって、マルチバイト対応のdiff(私の場合vimはdiffモード)を選択して、のgit difftool代わりに使用してくださいgit diff

「difftool」が長すぎて入力できませんか?問題ない:

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

Git rocks。


1
完璧な解決策ではありませんが(スクロールして統一されたdiffが必要です)、しかし、選択肢があり、インストールする新しいものを見つけたくないという私の意欲を考えると、それはそれほど悪ではありません。「vimdiff」です!(そう、vim ...とgit)
Roboprog

1
これは、UTF16ファイルのチャンクのみをステージングおよびコミットするためにも機能しますか?
Ortwin Gentz

Beyond Compareを比較およびマージツールとして使用しています。.gitconfig <pre> <code> [difftool "bc3"]からパス= c:/ Program Files(x86)/ Beyond Compare 3 / bcomp.exe [mergetool "bc3"]パス= c:/ Program Files(x86)/ Beyond Compare 3 / bcomp.exe </ code> </ pre>
トムウィルソン

@トム・ウィルソン4スペースをインデントしてコードブロックをフォーマットできません!?
トムウィルソン

私はgitの基本的な知識を持っていますが、それがファイルの変更を処理する方法がわかりません。これは常にバイナリファイルですか、それともテキスト(ASCII)の場合、特別な処理/変更の検出がありますか?
i486

63

Unicesでそのまま使用できる非常にシンプルなソリューションがあります。

たとえば、Appleの.stringsファイルでは次のようになります。

  1. .gitattributesリポジトリのルートにファイルを作成します。

    *.strings diff=localizablestrings
    
  2. 以下を~/.gitconfigファイルに追加します。

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

出典:GitのDiff .stringsファイル(および2010年以降の古い投稿)。


私はこれを行いましたが、gitはこれ以降の実行を拒否します。私が受け取るエラーは、「/ Users / myusername / .gitconfigの不良構成ファイル4行目」です。「git config --global --edit」を使用してgitconfigファイルを開きました。興味深いことに、追加した行を削除すると、すべて正常に機能します。手がかりはありますか?
shshnk 2014年

コピー/貼り付けした場合は、スマートクォートを推測します。私はそれを修正するために答えを編集しました。
Lou Franco 14

これは魅力のように機能します。シンプルにするため、およびより良い統合のために、これは受け入れられる答えになるはずです。「別のツールを使用する」が「gitにUTF-16ファイルをテキストとして認識させることはできますか?」
itMaxence 2018

@itMaxence厳密にiconvは、VimまたはBeyond Compareとまったく同じ方法で「別のツール」です(gitスイートの一部ではありません)。
Agi Hammerthief 2018

@AgiHammerthief確かにもう一度読んだ後、同意します。FWIW vimdifficonvどちらもすでにmacOSに存在しているので、どこで入手するか
迷う

39

.gitattributesテキストファイルとして扱うように設定しましたか?

例えば:

*.vmc diff

詳細については、http://www.git-scm.com/docs/gitattributes.htmlをご覧ください


2
この作品は、しかし正確さに注意してください、このセット2つの属性:setdiff...
OK。

2
この解決策は私にとって唯一許容できるものです。@OKコメントによると、「セット」はここでは関係ありません。指定したパスの「diff」属性を設定するには*.vmc diff*.sql diffなどが必要です。(私は答えを編集することはできません)。ただし、2つの注意点:diffは各文字の間にスペースを入れて表示され、問題のあるファイルの「ハンクのステージング」または「ハンクの破棄」はできません。
Pac0 2017年

30

デフォルトでは、gitUTF-16ではうまく機能しないようです。このようなファイルの場合、CRLF処理が行われていないことを確認する必要がありますがdiffmerge、通常のテキストファイルとして機能させるます(これは、ターミナル/エディターがUTF-16を処理できるかどうかを無視しています)。

しかし、.gitattributesマンページを見ると、次のようなカスタム属性がありbinaryます。

[attr]binary -diff -crlf

したがって、トップレベル.gitattributesでカスタム属性を定義できるように思えますutf16(テキストとして扱われるように、ここにマージを追加していることに注意してください)。

[attr]utf16 diff merge -crlf

そこから、次の.gitattributesようなファイルを指定できます。

*.vmc utf16

また、次のようにバイナリであると考えられdiffている場合でも、ファイルにアクセスできるはずですgit

git diff --text

編集する

この回答は基本的に、GNU diffとUTF-16またはUTF-8でもうまく機能しないことを示しています。git別のツールを使用して(を介して--ext-diff)違いを確認したい場合、その答えはGuiffyを示唆しています。

しかし、おそらく必要なのはdiff、ASCII文字のみを含むUTF-16ファイルだけです。これを機能させる方法は--ext-diff、次のシェルスクリプトを使用することです。

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

UTF-8への変換はマージでも機能することに注意してください。両方の方向で行われることを確認する必要があります。

UTF-16ファイルのdiffを見るときのターミナルへの出力に関しては:

そのように差分を取ろうとすると、バイナリのゴミが画面に吐き出されます。gitがGNU diffを使用している場合、GNU diffはユニコードに対応していないように見えます。

GNU diffは本当にユニコードを気にしないので、diff --textを使用すると、diffしてテキストを出力します。問題は、使用している端末が(ASCII文字であるdiffマークと組み合わせて)発行されたUTF-16を処理できないことです。


そのように差分を取ろうとすると、バイナリのゴミが画面に吐き出されます。gitがGNU diffを使用している場合、GNU diffはユニコードに対応していないように見えます。
スキップホッピー2009

1
GNU diffは本当にユニコードを気にしないので、diff --textを使用すると、diffしてテキストを出力します。問題は、使用している端末が(ASCII文字であるdiffマークと組み合わせて)発行されたUTF-16を処理できないことです。
Jared Oberhaus、

@ jared-oberhaus-特定のタイプのファイル(つまり、特定の拡張子)に対してのみこのスクリプトをトリガーする方法はありますか?
テリー

8

解決策は、でフィルタリングすることcmd.exe /c "type %1"です。cmdのtype組み込みが変換を行うので、それをgit diffのtextconv機能で使用して、UTF-16ファイルのテキスト比較を有効にすることができます(テストされていませんが、UTF-8でも機能するはずです)。

gitattributesのmanページからの引用:


バイナリファイルのテキスト差分を実行する

一部のバイナリファイルのテキスト変換されたバージョンの差分を確認することが望ましい場合があります。たとえば、ワードプロセッサドキュメントをASCIIテキスト表現に変換し、テキストの差分を表示できます。この変換では一部の情報が失われますが、結果の差分は人間が見るのに役立ちます(ただし、直接適用することはできません)。

textconv構成オプションは、そのような変換を実行するためのプログラムを定義するために使用されます。プログラムは単一の引数、つまり変換するファイルの名前を受け取り、結果のテキストをstdoutに生成します。

たとえば、バイナリ情報の代わりにファイルのexif情報の差分を表示するには(exifツールがインストールされていることが前提)、次のセクションを$GIT_DIR/configファイル(または$HOME/.gitconfigファイル)に追加します。

[diff "jpg"]
        textconv = exif

mingw32のソリューション、cygwinファンの、アプローチを変更する必要があるかもしれません。問題は、cmd.exeに変換するファイル名を渡すことです-スラッシュを使用し、cmdはバックスラッシュディレクトリ区切り文字を想定します。

ステップ1:

stdoutへの変換を行う単一引数のスクリプトを作成します。c:\ path \ to \ some \ script.sh:

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

ステップ2:

スクリプトファイルを使用できるようにgitを設定します。git config内(~/.gitconfigまたはを.git/config参照man git-config)に、次のように入力します。

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

ステップ3:

.gitattributesファイル(man gitattributes(5)を参照)を使用して、このworkarondを適用するファイルを指摘します。

*vmc diff=cmdtype

次にgit diff、ファイルで使用します。


トニーKuneckさんなどが、「C:/path/to/some/script.sh」なしほとんどentropy.ch/blog/Developer/2010/04/15/...
アレクセイShumkin

上記のGit for Windowsのスクリプトに問題がありますが、次のコードは問題なく、パス内のスペースも処理できることがわかりましたcmd //c type "${1//\//\\}"
patthoyts 2013

:これは、スクリプト・ファイルを作成しなくても動作しますtextconv = powershell -NoProfile -Command \"& {Get-Content \\$args[0]}\"
ヤクブBerezanski

5

gitは最近、utf16などのエンコーディングを理解し始めました。gitattributesのドキュメントを参照して検索working-tree-encoding

[これはかなり新しいので、manページが一致していることを確認してください!]

(言う)ファイルは、Windowsマシン上でBOMなしUTF-16であれば、あなたに追加.gitattributesのファイル

*.vmc text working-tree-encoding=UTF-16LE eol=CRLF

* nixでUTF-16(BOMを使用)の場合は、次のようにします。

*.vmc text working-tree-encoding=UTF-16-BOM eol=LF

(置き換え*.vmc*.whateverするためにwhateverあなたがハンドルに必要なタイプのファイル)

参照:サポート作業ツリーエンコーディング "UTF-16LE-BOM"


後で追加

@Hackslashに続いて、これは不十分であることがわかるかもしれません

 *.vmc text working-tree... 

必要なテキストの差分を取得するには

 *.vmc diff working-tree...

両方の作品も置く

 *.vmc text diff working-tree... 

しかし、それは間違いなく

  • 冗長— eol=...意味するtext
  • 冗長—大規模なプロジェクトでは、数十種類のテキストファイルタイプを簡単に作成できます

問題

Gitにはを意味するマクロ属性が binaryあります-text -diff。反対+text +diffは組み込みでは利用できませんが、gitはそれを合成するためのツール(私はそう思います!)を提供します

ソリューション

Gitでは、新しいマクロ属性を定義できます。

私は.gitattributesあなたが持っているファイルのトップを提案します

 [attr]textfile text diff

次に、テキストおよび差分にする必要があるすべてのパスについて

 path textfile working-tree-encoding= eol=...

ほとんどの場合、デフォルトのエンコーディング(utf-8)とデフォルトのeol(ネイティブ)が必要であるため、削除される可能性があることに注意してください。

ほとんどの行は次のようになります

textfile *.c
textfile *.py
Etc

なぜdiffを使用しないのですか?

実用:ほとんどの場合、ネイティブeolが必要です。いいえを意味しeol=...ます。そのtextため、黙示的ではなく、明示的に配置する必要があります。

概念:テキストとバイナリーが基本的な違いです。eol、encoding、diffなどは、ほんの一部の側面です。

免責事項

私たちが住んでいる奇妙な時期のため、現在動作しているGitを備えたマシンはありません。そのため、現時点では最新の追加情報を確認できません。誰かが何か問題を見つけた場合、私はエメンド/削除します。


仕事に私のUTF-16LE-BOMファイルを取得するために私が使用していた*.vmc diff working-tree-encoding=UTF-16LE-BOM eol=CRLF
HackSlash

@HackSlash:ヘッズアップありがとうございます。私はあなたがtext一人であなたが素晴らしいテキスト差分を得られなかったと言っていると思いますか?あなたがそれをチェックしてくださいすることができ、両方 textdiffすべてが正常に動作しますか?その場合、私は別の推奨事項を行います
Rusi

正しく、text単独ではバイナリ比較になります。私はできるdifftext diff、それでうまくいく。-BOMファイルにBOM、YMMVが含まれているため、追加する必要がありました。
HackSlash

@HackSlash私はあなたの発見を取り入れました。ぜひチェックしてみてくださいね!
ルシ

@Rusiに感謝します、私には理にかなっています。
HackSlash

4

小さなgit-diffドライバーto-utf8を作成しました。これにより、ASCII / UTF-8以外でエンコードされたファイルを簡単に比較できます。https://github.com/chaitanyagupta/gitutils#to-utf8の手順を使用してインストールできますto-utf8スクリプトは同じリポジトリで入手できます)。

このスクリプトでは、システムでコマンドfileiconvコマンドの両方を使用できる必要があることに注意してください。


2

最近Windowsでこの問題が発生しました。Windows用のgitに同梱されているdos2unixunix2dosbinがうまくいきました。デフォルトでは、これらはにありC:\Program Files\Git\usr\bin\ます。これが機能するのは、ファイルがUTF-16である必要がない場合のみです。たとえば、誰かがpythonファイルを(私の場合)必要のないときに誤ってUTF-16にエンコードしました。

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

そして

PS C:\Users\xxx> unix2dos my_file.py
unix2dos: converting UTF-16LE file my_file.py to ANSI_X3.4-1968 DOS format...
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.