Mengapa Git memperlakukan file teks ini sebagai file biner?

150

Aku bertanya-tanya mengapa git memberitahuku ini :?

$ 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

Bukankah itu file teks?

Saya telah memeriksa .gitattributes dan kosong. Mengapa saya menerima pesan ini? Saya tidak bisa mendapatkan difs seperti yang saya gunakan lagi

TAMBAH:

Saya perhatikan ada @di dalam izin file, apa ini? Dapatkah ini menjadi alasan?

$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
sumber
4
Ini bisa berupa file yang disandikan UTF-8.
Marnix van Valen
Ini seharusnya menjadi UTF16 little endian LF
nacho4d
1
Dari lsmanual di Mac OS X: Jika file atau direktori memiliki atribut yang diperluas, bidang izin yang dicetak oleh -lopsi diikuti oleh @karakter . Gunakan opsi -@untuk melihat atribut yang diperluas ini.
adl
Saya pikir ini bisa menjadi bug git. Saya menghapus atribut yang diperluas dan sekarang semuanya baik-baik saja.
nacho4d
4
@ nacho4d: Aneh, karena git seharusnya tidak tahu bahwa ada atribut tambahan. Jika Anda dapat mereproduksinya, ada baiknya Anda membuka milis git. Seperti kebiasaan yang baik pada vger.kernel.orgdaftar, Anda tidak harus berlangganan untuk mengirim (orang akan membuat Anda mendapat CC'ed untuk jawaban) dan agaknya tidak diberi volume [email protected]daftar yang cukup tinggi .
Jan Hudec

Jawaban:

76

Ini hanya berarti bahwa ketika git memeriksa konten sebenarnya dari file (itu tidak tahu bahwa ekstensi yang diberikan bukan file biner - Anda dapat menggunakan file atribut jika Anda ingin mengatakannya secara eksplisit - lihat halaman manual).

Setelah memeriksa isi file, ia telah melihat hal-hal yang tidak dalam karakter ascii dasar. Menjadi UTF16 saya berharap itu akan memiliki karakter 'lucu' sehingga menganggapnya biner.

Ada beberapa cara untuk memberitahu git jika Anda memiliki internasionalisasi (i18n) atau format karakter yang diperluas untuk file tersebut. Saya tidak cukup yakin tentang metode yang tepat untuk pengaturan itu - Anda mungkin perlu RT [Lengkap] M ;-)

Sunting: pencarian cepat SO yang ditemukan can-i-make-git-mengenali-file-utf-16-sebagai-teks yang akan memberi Anda beberapa petunjuk.

Philip Oakley
sumber
10
Anda hampir tetapi tidak sepenuhnya tidak salah. Git memang telah memeriksa file yang sebenarnya dan telah melihat karakter 'lucu' di sana. Namun itu tidak "berpikir" UTF-16 adalah biner. Ini adalah biner, karena teks didefinisikan sebagai berbasis ASCII (itulah satu-satunya perbedaan built-in yang akan memberikan hasil yang dapat digunakan untuk) dan UTF-16 tidak. Ya, ada cara untuk memberitahu git untuk menggunakan diff khusus untuk file-file yang didefinisikan pola (menggunakan .gitattributes).
Jan Hudec
2
Saya harus menambahkan, bahwa 'karakter lucu' benar-benar berarti nol byte.
Jan Hudec
4
Kami berdua benar, tetapi dari sudut pandang yang berbeda. Kami berdua mengatakan "Git memeriksa konten untuk menentukan jenisnya." Kami berdua mengatakan bahwa untuk membuat git tahu itu harus diperlakukan sebagai UTF16, pengguna harus memberi tahu git melalui .gitattributesdll.
Philip Oakley
7
@ JanHudec: Dalam pandangan Anda, SEMUA file adalah biner.
stolsvik
2
@stolosvik, (dan JanH) Ini adalah jalan tengah yang lebih halus dalam UTF-8 yang mencakup karakter dasar 0-127 ASCII, dan semua karakter Unicode lainnya, tanpa memerlukan byte nol (00j) untuk apa pun selain nul char (terminator string 'C'). Jadi definisi teks Git adalah bahwa konten (yah byte pertama 1k) tidak boleh memiliki byte nol ketika utf-8 dikodekan. Coba stackoverflow.com/questions/2241348/… untuk kesenangan membaca. Komentar asli saya merujuk pada kasus ketika data yang disandikan UTF-16 dipandang sebagai pasangan byte, sehingga byte tinggi untuk titik kode ascii akan menjadi 00.
Philip Oakley
41

Jika Anda belum menetapkan tipe file, Git mencoba menentukannya secara otomatis dan file dengan garis yang sangat panjang dan mungkin beberapa karakter lebar (mis. Unicode) diperlakukan sebagai biner. Dengan file .gitattributes Anda dapat menentukan bagaimana Git menafsirkan file. Mengatur atribut diff secara manual memungkinkan Git menginterkrip isi file sebagai teks dan akan melakukan diff biasa.

Cukup tambahkan .gitattributes ke folder root repositori Anda dan atur atribut diff ke paths atau file. Ini sebuah contoh:

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

Jika Anda ingin memeriksa apakah ada atribut yang ditetapkan pada file, Anda dapat melakukannya dengan bantuan git check-attr

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

Referensi bagus lainnya tentang atribut Git dapat ditemukan di sini .

naitsirch
sumber
1
Ini membantu, tetapi sebenarnya salah - atribut yang tepat adalah difftidak text. The textatribut tidak memberitahu git untuk diff menggunakan teks melainkan kontrol bagaimana akhir baris ditangani (normalisasi untuk LF). Lihat tautan Anda ke .gitattributes untuk lebih jelasnya.
ErikE
Terima kasih @ErikE. Saya telah memperbarui posting saya sesuai dengan komentar Anda dan dokumentasi Git.
naitsirch
4
Selain itu, Anda dapat mengatur jenis diff apa yang harus dilakukan. Misalnya, jika ini adalah file xml yang dapat Anda gunakan, diff=xmlbukan hanya diff.
Sandy Chapman
1
Apa kebalikan dari check-attr - apakah ada set-attr? Saya awalnya secara tidak sengaja menyimpan file sebagai UTF-16, kemudian melakukan dan mendorongnya, dan sekarang BitBucket melihatnya sebagai UTF-16, bahkan setelah menyimpannya kembali sebagai UTF-8, melakukan dan mendorongnya lagi. Ini pada dasarnya membuat permintaan tarikan saya mustahil untuk dibaca karena pengulas perlu mengklik setiap komentar individu untuk menambahkan komentar ulasan.
John Zabroski
21

Saya mengalami masalah ini ketika Git GUI dan SourceTree memperlakukan file Java / JS sebagai biner dan karenanya tidak dapat melihat perbedaan

Membuat file bernama "atribut" di folder .git \ info dengan konten berikut menyelesaikan masalah

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

Jika Anda ingin membuat perubahan ini untuk semua repositori maka Anda dapat menambahkan file atribut di lokasi berikut $ HOME / .config / git / atribut

Hemant
sumber
1
Perhatikan juga <project-root>/.gitattributesfile, yang membuat perubahan aktif untuk semua kontributor, dan hanya untuk proyek yang relevan.
jpaugh
Menambahkan * diffbermanfaat bagi saya: ini menunjukkan perbedaan dalam semua jenis file. Tetapi solusi Anda lebih baik, karena menghindari menunjukkan perbedaan yang tidak perlu dalam file biner besar.
Boolean_Type
Ya! Ini membantu!
WildCat
19

Git bahkan akan menentukan bahwa itu adalah biner jika Anda memiliki satu baris super panjang dalam file teks Anda. Saya putus String panjang, mengubahnya menjadi beberapa baris kode sumber, dan tiba-tiba file berubah dari 'biner' menjadi file teks yang bisa saya lihat (di SmartGit).

Jadi jangan terus mengetik terlalu jauh ke kanan tanpa menekan 'Enter' di editor Anda - jika tidak nanti Git akan berpikir Anda telah membuat file biner.

Chris Murphy
sumber
1
Ini adalah informasi yang benar. Saya mencoba untuk mengontrol diff ke file MySQL Dump (.sql) yang sangat besar, tetapi git memperlakukannya sebagai file biner, walaupun hanya memiliki data ASCII / UTF8 di dalamnya. Alasannya, adalah bahwa garis-garisnya super panjang (memasukkan nilai (satu), (dua), (tiga), (...), (3 juta ...); Anehnya, untuk setiap komit, repositori git tidak tidak bertambah 1,7gb, tetapi hanya ~ 350mb. Mungkin, git sedang mengompresi file "biner" sebelum menyimpannya
Alexandre T.
@AlexandreT. Git memang kompres gumpalan file (menggunakan GZip, IIRC).
jpaugh
11

Saya memiliki masalah yang sama setelah mengedit salah satu file saya di editor baru. Ternyata editor baru menggunakan pengkodean yang berbeda (Unicode) dari editor lama saya (UTF-8). Jadi saya hanya mengatakan kepada editor baru saya untuk menyimpan file saya dengan UTF-8 dan kemudian git menunjukkan perubahan saya dengan benar lagi dan tidak melihatnya sebagai file biner.

Saya pikir masalahnya hanya git yang tidak tahu bagaimana membandingkan file dari jenis pengkodean yang berbeda. Jadi tipe pengkodean yang Anda gunakan benar-benar tidak masalah, asalkan tetap konsisten.

Saya tidak mengujinya, tapi saya yakin jika saya hanya akan melakukan file saya dengan pengkodean Unicode baru, kali berikutnya saya membuat perubahan pada file itu akan menunjukkan perubahan dengan benar dan tidak terdeteksi sebagai biner, karena maka itu akan membandingkan dua file yang dikodekan Unicode, dan bukan file UTF-8 ke file Unicode.

Anda dapat menggunakan aplikasi seperti Notepad ++ untuk dengan mudah melihat dan mengubah jenis penyandian file teks; Buka file di Notepad ++ dan gunakan menu Encoding di bilah alat.

deadlydog
sumber
1
Unicode bukan penyandian. Ini adalah rangkaian karakter dan UTF-8 adalah salah satu penyandiannya, yaitu cara untuk menyandikan titik
kode
1
Ini tidak menyelesaikan masalah, hanya menghindarinya. Masalahnya adalah bahwa git atau alat diff-nya tidak mengenali file teks dengan benar atau tidak dengan mudah memungkinkan pengguna untuk menimpa perilakunya.
Preza8
6

Saya memiliki masalah yang sama. Saya menemukan utas ketika saya mencari solusi di google, masih saya tidak menemukan petunjuk. Tapi saya pikir saya menemukan alasan setelah belajar, contoh di bawah ini akan menjelaskan dengan jelas petunjuk saya.

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

untuk saat ini, file new.txt dianggap sebagai file teks.

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

Anda akan mendapatkan hasil ini

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

dan coba ini

git diff -a

Anda akan mendapatkan di bawah ini

    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
sumber
5

Kami memiliki kasus ini di mana file .html dilihat sebagai biner setiap kali kami mencoba membuat perubahan di dalamnya. Sangat tidak keren untuk tidak melihat diff. Sejujurnya, saya tidak memeriksa semua solusi di sini tetapi yang berhasil bagi kami adalah sebagai berikut:

  1. Menghapus file (sebenarnya memindahkannya ke Desktop saya) dan melakukan git deletion. Kata GitDeleted file with mode 100644 (Regular) Binary file differs
  2. Menambahkan kembali file (sebenarnya memindahkannya dari Desktop saya kembali ke proyek). Git mengatakan New file with mode 100644 (Regular) 1 chunk, 135 insertions, 0 deletionsFile itu sekarang ditambahkan sebagai file teks biasa

Mulai sekarang, setiap perubahan yang saya buat dalam file dilihat sebagai perbedaan teks biasa. Anda juga dapat menekan komitmen ini (1, 2, dan 3 sebagai perubahan aktual yang Anda buat) tetapi saya lebih suka untuk dapat melihat di masa depan apa yang saya lakukan. Squashing 1 & 2 akan menampilkan perubahan biner.

StuFF mc
sumber
Mirip dengan satu atau dua file cpp (berhasil dikompilasi) yang didorong dari VS. Memberi Github gui untuk Bandingkan menggelikan. Seseorang tidak ingin menjadi lalat di bel dalam pertukaran ding dong, - VS di satu sisi mengatakan itu Github, dan di sisi lain Github mengatakan itu VS. :(
Laurie Stearn
4

Per jawaban yang bermanfaat ini , Anda dapat bertanya langsung kepada Git mengapa ia memperlakukan file dengan cara tertentu:

cd directory/of/interest
file *

Ini menghasilkan keluaran yang bermanfaat seperti ini:

$ 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
sumber
6
filebukan perintah git. Ini adalah alat yang sepenuhnya terpisah yang dikemas dengan git di Windows. Apakah ada dokumentasi yang menunjukkan bahwa inilah yang digunakan git untuk deteksi file biner?
Maks
4

Ini juga disebabkan (pada Windows setidaknya) oleh file teks yang memiliki UTF-8 dengan pengkodean BOM . Mengubah encoding ke UTF-8 biasa segera membuat Git melihat file sebagai type = teks

Robba
sumber
1

Saya memiliki contoh di mana .gitignoreberisi \rurutan ganda (carriage return) dengan sengaja.

File itu diidentifikasi sebagai biner oleh git. Menambahkan .gitattributesfile membantu.

# .gitattributes file
.gitignore diff
Erik Zivkovic
sumber
1
Bekerja. Saya juga punya dua file untuk mengabaikan beberapa file "Ikon" OS. Baik untuk mengetahui penyebabnya serta cara memperbaikinya.
hsandt
1

Jika git check-attr --all -- src/my_file.txtmenunjukkan bahwa file Anda ditandai sebagai biner, dan Anda belum menetapkannya sebagai biner .gitattributes, periksa di /.git/info/attributes.

coberlin
sumber
0

Ubah Aux.js ke nama lain, seperti Sig.js.

Source tree masih menunjukkannya sebagai file biner, tetapi Anda bisa membuat stage (menambahkan) dan komit.

Oscar Zhou1989
sumber
0

Saya memiliki masalah yang sama ketika saya menempelkan beberapa teks dari pesan biner Kafka, yang menyisipkan karakter yang tidak terlihat dan membuat git berpikir file tersebut biner.

Saya menemukan karakter yang menyinggung dengan mencari file menggunakan regex [^ -~\n\r\t]+.

  • [ cocokkan karakter dalam set ini
  • ^ karakter yang cocok tidak ada di set ini
  • -~ cocok dengan semua karakter dari '' (spasi) hingga '~'
  • \n garis baru
  • \r Kereta kembali
  • \t tab
  • ] set dekat
  • + cocokkan satu atau lebih dari karakter ini
Martyn Davis
sumber
-2

Saya hanya menghabiskan beberapa jam memeriksa semua yang ada di daftar ini mencoba mencari tahu mengapa salah satu proyek pengujian dalam solusi saya tidak menambahkan tes apa pun pada penjelajah.

Ternyata dalam kasus saya bahwa entah bagaimana (mungkin karena git miskin bergabung di suatu tempat) yang VS telah kehilangan referensi proyek sama sekali. Itu masih membangun tetapi saya perhatikan bahwa itu hanya membangun ketergantungan.

Saya kemudian memperhatikan bahwa itu tidak muncul dalam daftar dependensi itu sendiri, jadi saya menghapus dan menambahkan kembali proyek uji dan semua tes saya akhirnya muncul.

awan tipis
sumber
2
Visual Studio benar-benar tidak relevan di sini.
jpaugh