Git'in UTF-16 dosyasını metin olarak tanımasını sağlayabilir miyim?


140

Git'te bir Sanal PC sanal makine dosyasını (* .vmc) izliyorum ve bir değişiklik yaptıktan sonra git dosyayı ikili olarak tanımladı ve benim için fark etmez. Dosyanın UTF-16'da kodlandığını keşfettim.

Git'in bu dosyanın metin olduğunu tanıması ve uygun şekilde işlemesi öğretilebilir mi?

Git Cygwin altında kullanıyorum, core.autocrlf false olarak ayarlanmış. Gerekirse UNIX altında mSysGit veya git kullanabilirsiniz.

Yanıtlar:


83

Bir süredir bu sorunla mücadele ediyorum ve sadece (benim için) mükemmel bir çözüm keşfettim:

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

git difftoolaynı argümanları alır git diff, ancak yerleşik GNU yerine seçtiğiniz farklı bir programı çalıştırır diff. Bu yüzden çok baytlı bir fark seçin (benim durumumda vimfark modunda) ve git difftoolyerine kullanın git diff.

"Difftool" yazmak için çok mu uzun? Sorun değil:

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

Git kayalar.


1
Mükemmel bir çözüm değil (kayan birleşik fark var), AMA, seçenekler ve yüklemek için yeni bir şey bulmak istemem göz önüne alındığında daha az kötüdür. "vimdiff", öyle! (evet, vim ... ve git)
Roboprog

1
Bu aynı zamanda yalnızca UTF16 dosyalarının bölümlerini düzenlemek ve işlemek için de işe yarıyor mu?
Ortwin Gentz

Kullandığım ötesinde karşılaştırın bir fark ve birleştirme aracı olarak kullanmaktadır. .Gitconfig <pre> <code> [difftool "bc3"] yol = c: / Program Dosyaları (x86) / Ötesinde Karşılaştır 3 / bcomp.exe [mergetool "bc3"] path = c: / Program Dosyaları (x86) / Ötesinde Karşılaştır 3 / bcomp.exe </code> </pre>
Tom Wilson

@Tom Wilson Maalesef 4 boşluğa girintiyle kod bloğunu biçimlendiremiyoruz !?
Tom Wilson

Git için temel bilgiye sahibim ve dosya değişikliklerini nasıl işlediğinden emin değilim. Bu her zaman ikili dosyalar mı yoksa metin (ASCII) için mi özel değişikliklerin işlenmesi / algılanması vardır?
i486

63

Unices üzerinde kutudan çıkan çok basit bir çözüm var.

Örneğin, Apple'ın .stringsdosyaları ile:

  1. Deponuzun .gitattributeskökünde aşağıdakilerle bir dosya oluşturun :

    *.strings diff=localizablestrings
    
  2. ~/.gitconfigDosyanıza aşağıdakileri ekleyin :

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

Kaynak: Git'teki farklı .strings dosyaları (ve 2010'dan daha eski yazı ).


Bunu yaptım ama git bundan sonra koşmayı reddediyor. Aldığım hata "/Users/myusername/.gitconfig dosyasındaki hatalı yapılandırma dosyası satırı 4". Gitconfig dosyamı açmak için "git config --global --edit" kullandım. İlginç bir şekilde eklenen satırları kaldırırsanız tüm iyi çalışıyor. Herhangi bir ipucu var mı?
shshnk

Kopyalarsanız / yapıştırırsanız akıllı tırnakları tahmin edeceğim. Bunu düzeltmek için cevabı düzenledim.
Lou Franco

Bu bir cazibe gibi çalışır, basitlik ve daha iyi bir entegrasyon için kabul edilen cevap olmalıdır. "Başka bir aracı kullan" ın "Git'in UTF-16 dosyasını metin olarak tanımasını sağlayabilir miyim?" Sorusunun cevabı olabileceğini görmüyorum.
itMaxence

@itMaxence Kesinlikle, iconvVim veya Beyond Compare ile aynı şekilde "başka bir araçtır" (git paketinin parçası değil).
Agi Hammerthief

@AgiHammerthief tekrar okuduktan sonra katılıyorum, ne düşündüğümü bilmiyorum. FWIW vimdiffve iconvher ikisi de macOS'ta zaten mevcut, bu yüzden onları nereden alacağınızı merak etmenize gerek yok ve işi
yapıyorlar

39

.gitattributesBir metin dosyası olarak işlemek için ayarlamayı denediniz mi?

Örneğin:

*.vmc diff

Daha fazla ayrıntı için http://www.git-scm.com/docs/gitattributes.html .


2
Bu işe yarar, ancak doğruluk için lütfen bunun iki özelliği ayarladığını unutmayın : setve diff...
Tamam.

2
Bu çözüm benim için tek kabul edilebilir. @OK açıklamasına göre, "set" burada anlamsızdır, sadece *.vmc diff, *.sql diffvs .. belirtilen yol için 'diff' niteliğini ayarlamak için gereklidir. (Cevabı düzenleyemiyorum). Ancak 2 uyarı: farklar her karakter arasında boşluk ile gösterilir ve bu sorunlu dosyalar için "sahne iri" veya "iri parça" atılması mümkün değildir.
Pac0

30

Varsayılan olarak, gitUTF-16 ile iyi çalışmaz gibi görünüyor ; böyle bir dosya için CRLFüzerinde hiçbir işlem yapılmadığından emin olmanız gerekir , ancak istediğiniz diffve mergenormal bir metin dosyası olarak çalışmanız gerekir (bu, terminalinizin / düzenleyicinizin UTF-16'yı işleyip işleyemeyeceğini görmezden gelir).

Ancak .gitattributesmanpage'e baktığımızda , şu özel özellik binary:

[attr]binary -diff -crlf

Eğer üst düzeyde bir özellik tanımlamak olabilir geliyor bana Yani .gitattributesiçin utf16(Emin metin olarak kabul edilir olmak için burada birleştirme eklemek o notta):

[attr]utf16 diff merge -crlf

Oradan herhangi bir .gitattributesdosyada şöyle bir şey belirtebilirsiniz :

*.vmc utf16

Ayrıca, diffbir dosya gitile ikili olduğunu düşünüyor olsa bile, bir dosyayı hâlâ kullanabilmeniz gerektiğini unutmayın :

git diff --text

Düzenle

Bu cevap temelde GNU'nun UTF-16'dan farklı olduğunu ve hatta UTF-8'in çok iyi çalışmadığını söylüyor. gitFarklılıkları görmek için farklı bir araç kullanmak istiyorsanız (üzerinden --ext-diff), bu cevap Guiffy'yi önerir .

Ancak, büyük olasılıkla diffyalnızca ASCII karakterleri içeren bir UTF-16 dosyasına ihtiyacınız vardır. Bunu işe almanın bir yolu kullanmak --ext-diffve aşağıdaki kabuk komut dosyasıdır:

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

UTF-8'e dönüştürmenin birleştirme için de işe yarayabileceğini, bunun her iki yönde de yapıldığından emin olmanız gerektiğini unutmayın.

UTF-16 dosyasının farkına bakarken terminale çıkış gelince:

Bu şekilde farklı olmaya çalışmak, ekrana ikili çöp atmasıyla sonuçlanır. Git GNU diff kullanıyorsa, GNU diff unicode farkında değildir.

GNU diff gerçekten unicode umurunda değil, bu yüzden diff --text kullandığınızda metni fark eder ve çıktı verir. Sorun, kullandığınız terminalin yayılan UTF-16'yı işleyememesidir (ASCII karakterleri olan fark işaretleriyle birlikte).


Bu şekilde farklı olmaya çalışmak, ekrana ikili çöp atmasıyla sonuçlanır. Git GNU diff kullanıyorsa, GNU diff unicode farkında değildir.
skiphoppy

1
GNU diff gerçekten unicode umurunda değil, bu yüzden diff --text kullandığınızda metni fark eder ve çıktı verir. Sorun, kullandığınız terminalin yayılan UTF-16'yı işleyememesidir (ASCII karakterleri olan fark işaretleriyle birlikte).
Jared Oberhaus

@ jared-oberhaus - bu komut dosyasını yalnızca belirli dosya türleri için tetiklemenin bir yolu var mı?
Terry

8

Çözüm filtrelemektir cmd.exe /c "type %1". cmd's typeyerleşkesi dönüştürmeyi yapar ve böylece UTF-16 dosyalarının metin farklılığını etkinleştirmek için git diff'in textconv yeteneğiyle kullanabilirsiniz (test edilmemiş olsa da UTF-8 ile de çalışmalıdır).

Gitattributes man sayfasından alıntı:


İkili dosyaların metin farklarını gerçekleştirme

Bazen bazı ikili dosyaların metin dönüştürülmüş bir versiyonunun farkını görmek istenebilir. Örneğin, bir kelime işlemci belgesi bir ASCII metin gösterimine ve gösterilen metnin farkına dönüştürülebilir. Bu dönüşüm bazı bilgileri kaybetse de, ortaya çıkan fark insanın izlenmesi için yararlıdır (ancak doğrudan uygulanamaz).

Textconv config seçeneği, bu tür bir dönüşümü gerçekleştirmek için bir program tanımlamak için kullanılır. Program tek bir argüman almalı, dönüştürülecek dosyanın ismini ve stdout üzerinde ortaya çıkan metni üretmelidir.

Örneğin, ikili bilgiler yerine bir dosyanın exif bilgilerinin farkını göstermek için (exif aracının yüklü olduğunu varsayarak), $GIT_DIR/configdosyaya (veya $HOME/.gitconfigdosyanıza) aşağıdaki bölümü ekleyin :

[diff "jpg"]
        textconv = exif

Mingw32 için bir çözüm olan cygwin hayranları bu yaklaşımı değiştirmek zorunda kalabilir. Sorun cmd.exe'ye dönüştürmek için dosya adını geçirmektir - eğik çizgi kullanır ve cmd ters eğik çizgi dizin ayırıcılarını varsayar.

Aşama 1:

Stdout'a dönüştürme yapacak tek argüman komut dosyasını oluşturun. c: \ yol \ bazı \ dosyanın tam \ olarak:

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

Adım 2:

Komut dosyasını kullanabilmek için git'i ayarlayın. Senin git yapılandırma (İç ~/.gitconfigveya .git/configya bakınız man git-config), bu koyun:

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

Aşama 3:

Bu geçici çözümü uygulamak için dosyaları .gitattributes dosyalarını kullanarak işaret edin (bkz. Man gitattributes (5)):

*vmc diff=cmdtype

sonra git diffdosyalarınızda kullanın .


Neredeyse Tony Kuneck'inki gibi ama "c: /path/to/some/script.sh" entropy.ch/blog/Developer/2010/04/15/…
Alexey Shumkin

Ben Windows için Git ile yukarıda gösterilen ama şu yoldaki boşluklar başa çıkabilirim da gayet iyi ve bulduğumuz gibi komut ile biraz problem var: cmd //c type "${1//\//\\}" .
patthoyts

Bu bir komut dosyası oluşturmaya gerek kalmadan çalışacaktır:textconv = powershell -NoProfile -Command \"& {Get-Content \\$args[0]}\"
Jakub Berezanski

5

git son zamanlarda utf16 gibi kodlamaları anlamaya başladı. Gitattributes dokümanı görün ,working-tree-encoding

[Bu oldukça yeni olduğu için man sayfanızın eşleştiğinden emin olun!]

(Diyelim) dosyası Windows makinesinde BOM olmadan UTF-16 ise daha sonra eklemek .gitattributesdosyası

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

* Nix'de UTF-16 (bomlu) yapıyorsanız:

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

(Değiştir *.vmcile *.whateveriçin whatevertip dosyaları size kolu gerekir)

Bkz. Çalışma ağacı kodlama "UTF-16LE-BOM" .


Daha sonra eklendi

@Hackslash'ın ardından bunun yetersiz olduğu görülebilir

 *.vmc text working-tree... 

Güzel metin farkları almak için ihtiyacınız olan

 *.vmc diff working-tree...

Her iki işi de koymak

 *.vmc text diff working-tree... 

Ama tartışmasız

  • Gereksiz - eol=...ima edertext
  • Ayrıntılı - büyük bir proje kolayca onlarca farklı metin dosyası türüne sahip olabilir

Sorun

Git'in bir makro özelliği binary vardır -text -diff. Bunun tersi +text +diffyerleşik değildir, ancak git sentezlemek için araçları (sanırım!) Verir.

Çözüm

Git, kişinin yeni makro niteliklerini tanımlamasına izin verir.

.gitattributesDosyanızın üst kısmının

 [attr]textfile text diff

Sonra metin ve fark olması gereken tüm yollar için

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

Çoğu durumda varsayılan kodlamanın (utf-8) ve varsayılan eol (yerel) olmasını isteyeceğiz ve bu nedenle bırakılabilir.

Çoğu çizgi şöyle görünmelidir

textfile *.c
textfile *.py
Etc

Neden sadece diff kullanmıyorsunuz?

Pratik: Çoğu durumda yerel eol istiyoruz. Bu da hayır demek eol=.... Yani textima edilmeyecek ve açık bir şekilde konulması gerekiyor.

Kavramsal: İkili Metin vs ikili ayrımdır. eol, kodlama, fark vb.

feragat

İçinde yaşadığımız tuhaf zamanlardan dolayı, şu anda çalışan bir makineye sahip değilim. Şu anda en son eklemeyi kontrol edemiyorum. Birisi yanlış bir şey bulursa, onu alırım / kaldırırım.


UTF-16LE-BOM *.vmc diff working-tree-encoding=UTF-16LE-BOM eol=CRLF
dosyamı çalıştırmak

@HackSlash: Uyarı için teşekkürler. Sanırım texttek başınıza güzel metin farkları alamadınız mı? Lütfen her ikisiyle de kontrol edebilir misiniz textve diffher şey yolunda mı? Bu durumda farklı bir öneri yapacağım
Rusi

Doğru, texttek başına ikili karşılaştırmaya neden olur. Yapabilirim diffya da text diffişe yarıyor. -BOMDosyamın bir Malzeme Listesi, YMMV olduğu için eklemem gerekiyordu .
HackSlash

@HackSlash Bulmanızı dahil ettim. Eğer kontrol eğer harika olurdu!
Rusi

Teşekkürler @Rusi, bana mantıklı geliyor.
HackSlash

4

to-utf8ASCII / UTF-8 kodlu olmayan dosyaları dağıtmayı kolaylaştıracak küçük bir git-diff sürücüsü yazdım . Buradaki talimatları kullanarak yükleyebilirsiniz: https://github.com/chaitanyagupta/gitutils#to-utf8 ( to-utf8komut dosyası aynı depoda mevcuttur).

Bu komut hem gerektirdiğini unutmayın fileve iconvkomutlar sistemde kullanılabilir olması için.


2

Son zamanlarda Windows'da bu sorun vardı ve windows için git ile birlikte gelen dos2unixve unix2doskutuları hile yaptı. Varsayılan olarak bulunurlar C:\Program Files\Git\usr\bin\. Dosyanızı eğer bu irade sadece işi gözlemleyin gelmez UTF-16 olması gerekir. Örneğin, birisi (benim durumumda) olması gerekmediğinde yanlışlıkla bir python dosyasını UTF-16 olarak kodladı.

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

ve

PS C:\Users\xxx> unix2dos my_file.py
unix2dos: converting UTF-16LE file my_file.py to ANSI_X3.4-1968 DOS format...
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.