เหตุใด Git จึงถือว่าไฟล์ข้อความนี้เป็นไฟล์ไบนารี


150

ฉันสงสัยว่าทำไมคอมไพล์บอกฉันนี้:

$ 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

พวกเขาไม่ใช่ไฟล์ข้อความเหรอ?

ฉันได้ตรวจสอบ. gitattributes แล้วและมันว่างเปล่า ทำไมฉันถึงได้รับข้อความนี้? ฉันไม่สามารถรับความแตกต่างได้เมื่อฉันใช้อีกต่อไป

เพิ่ม:

ฉันสังเกตเห็นว่ามีการ@อนุญาตในไฟล์นี่คืออะไร นี่อาจเป็นเหตุผลหรือไม่

$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

4
อาจเป็นไฟล์ที่เข้ารหัส UTF-8
Marnix van Valen

มันควรจะเป็น UTF16 เล็ก ๆ น้อย ๆ endian LF
nacho4d

1
จากlsmanpage บน Mac OS X: ถ้าแฟ้มหรือไดเรกทอรีมีคุณสมบัติการขยายสนามสิทธิ์พิมพ์โดย-lตัวเลือกที่จะตามด้วย@ตัวอักษร ใช้ตัวเลือก-@เพื่อดูแอตทริบิวต์เพิ่มเติมเหล่านี้
adl

ฉันคิดว่านี่อาจเป็นข้อผิดพลาดของคอมไพล์ ฉันลบแอตทริบิวต์เพิ่มเติมและตอนนี้ทุกอย่างเรียบร้อยดีอีกครั้ง
nacho4d

4
@ nacho4d: มันแปลกเพราะคอมไพล์ไม่ควรรู้ด้วยซ้ำว่ามันมีคุณสมบัติเพิ่มเติม หากคุณสามารถสร้างมันขึ้นมาใหม่มันจะคุ้มค่าที่จะนำขึ้นรายการจดหมายข่าวทางคอมไพล์ ตามธรรมเนียมที่ดีในvger.kernel.orgรายการคุณไม่จำเป็นต้องสมัครสมาชิกเพื่อโพสต์ (ผู้คนจะคอยให้คุณ CC'ed เพื่อหาคำตอบ) และเป็นประเภทที่ไม่ควรให้ปริมาณค่อนข้างสูงของgit@vger.kernel.orgรายการ
Jan Hudec

คำตอบ:


76

หมายความว่าเมื่อ git ตรวจสอบเนื้อหาจริงของไฟล์ (ไม่ทราบว่าส่วนขยายใด ๆ ที่ให้ไม่ใช่ไฟล์ไบนารี - คุณสามารถใช้ไฟล์แอตทริบิวต์ได้หากต้องการบอกอย่างชัดเจน - ดู man pages)

เมื่อตรวจสอบเนื้อหาของไฟล์แล้วจะเห็นสิ่งที่ไม่ได้อยู่ในอักขระ ASCII พื้นฐาน เป็น UTF16 ฉันคาดหวังว่ามันจะมีตัวละคร 'ตลก' ดังนั้นจึงคิดว่ามันเป็นเลขฐานสอง

มีวิธีบอก git หากคุณมีความเป็นสากล (i18n) หรือรูปแบบอักขระเพิ่มเติมสำหรับไฟล์ ฉันไม่เพียงพอกับวิธีการที่ถูกต้องสำหรับการตั้งค่านั้น - คุณอาจต้อง RT [Full] M ;-)

แก้ไข: การค้นหาอย่างรวดเร็วของ SO พบcan-i-make-git-recogn-a-utf-16-file-as-textซึ่งควรจะให้เบาะแสคุณไม่กี่


10
คุณเกือบจะสมบูรณ์ แต่ไม่ผิดเลย Git ตรวจสอบไฟล์จริงแล้วและได้เห็นตัวละคร "ตลก" ที่นั่น อย่างไรก็ตามมันไม่ได้ "คิดว่า" UTF-16 เป็นเลขฐานสอง มันเป็นเลขฐานสองเนื่องจากข้อความถูกกำหนดเป็นแบบ ASCII (นั่นเป็นเพียงสิ่งเดียวที่ diff ในตัวจะให้ผลลัพธ์ที่ใช้ได้) และ UTF-16 ไม่ใช่ ใช่มีวิธีบอก git ให้ใช้ diff พิเศษสำหรับไฟล์ที่กำหนดรูปแบบ (โดยใช้.gitattributes)
Jan Hudec

2
ฉันควรจะเพิ่มนั่นคือ 'ตัวละครตลก' จริงๆหมายถึงศูนย์ไบต์
Jan Hudec

4
เราทั้งคู่ถูกต้อง แต่จากมุมมองที่แตกต่างกัน เราทั้งคู่พูดว่า "Git ตรวจสอบเนื้อหาเพื่อกำหนดประเภทของเนื้อหา" เราทั้งคู่บอกว่าการทำให้คอมไพล์รู้ว่ามันควรจะได้รับการปฏิบัติเหมือน UTF16 ผู้ใช้จำเป็นต้องบอกคอมไพล์ผ่านทาง.gitattributesอื่น ๆ
Philip Oakley

7
@JanHudec: ในมุมมองของคุณไฟล์ทั้งหมดเป็นไบนารี
stolsvik

2
@stolosvik, (และ JanH) มันเป็นจุดกึ่งกลางที่ลึกซึ้งยิ่งขึ้นใน UTF-8 ที่มีทั้งอักขระฐาน 0-127 ASCII และอักขระ Unicode อื่น ๆ ทั้งหมดโดยไม่ต้องใช้ null (00h) ไบต์สำหรับสิ่งอื่นนอกเหนือจาก nul char (ตัวคั่นสตริง 'C') ดังนั้นการกำหนดข้อความของ Git คือเนื้อหา (ดี 1k ไบต์แรก) ไม่ควรมีค่า null เมื่อทำการเข้ารหัส utf-8 ลองใช้stackoverflow.com/questions/2241348/…เพื่อความสนุกในการอ่าน ความคิดเห็นดั้งเดิมของฉันอ้างถึงกรณีที่มีการดูข้อมูลที่เข้ารหัส UTF-16 เป็นคู่ไบต์ดังนั้นไบต์ที่สูงสำหรับคะแนนรหัส ASCII จะเป็น 00.
Philip Oakley

41

หากคุณไม่ได้ตั้งค่าประเภทของไฟล์ Git จะพยายามตรวจสอบโดยอัตโนมัติและไฟล์ที่มีเส้นที่ยาวมากและอาจเป็นอักขระที่มีความกว้าง (เช่น Unicode) เป็นไบนารี ด้วยไฟล์. gitattributesคุณสามารถกำหนดวิธีที่ Git ตีความไฟล์ การตั้งค่าแอททริบิวต์diff จะช่วยให้ Git interprete เนื้อหาไฟล์เป็นข้อความและจะทำ diff ตามปกติ

เพียงเพิ่ม. gitattributesไปยังโฟลเดอร์ root ของที่เก็บของคุณและตั้งค่าแอตทริบิวต์diffให้กับพา ธ หรือไฟล์ นี่คือตัวอย่าง:

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

หากคุณต้องการตรวจสอบว่ามีการตั้งค่าคุณลักษณะในไฟล์คุณสามารถทำได้ด้วยความช่วยเหลือของgit check-attr

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

อ้างอิงอื่นที่ดีเกี่ยวกับคุณลักษณะ Git อาจจะพบได้ที่นี่


1
นี้จะเป็นประโยชน์ แต่เป็นจริงไม่ถูกต้อง - แอตทริบิวต์ที่ถูกต้องคือไม่diff textแอtextททริบิวไม่ได้บอกให้คอมไพล์แตกต่างโดยใช้ข้อความ แต่ให้ควบคุมวิธีจัดการกับการสิ้นสุดบรรทัด ดูลิงก์ของคุณเพื่อ. gitattributes สำหรับรายละเอียดเพิ่มเติม
ErikE

ขอบคุณ @ErikE ฉันได้อัปเดตโพสต์ของฉันตามความคิดเห็นของคุณและเอกสาร Git
naitsirch

4
นอกจากนี้คุณสามารถกำหนดประเภทของ diff ที่ควรทำ ตัวอย่างเช่นหากเป็นไฟล์ xml คุณสามารถใช้diff=xmlแทนdiffได้
Sandy Chapman

1
ตรงกันข้ามกับ check-attr - มี set-attr หรือไม่? เดิมทีฉันบันทึกไฟล์เป็น UTF-16 โดยไม่ได้ตั้งใจจากนั้นให้คอมมิตและผลักดันมันและตอนนี้ BitBucket เห็นว่าเป็น UTF-16 แม้หลังจากบันทึกเป็น UTF-8 อีกครั้ง สิ่งนี้ทำให้การร้องขอการดึงของฉันเป็นไปไม่ได้เนื่องจากผู้ตรวจสอบต้องคลิกในแต่ละความคิดเห็นเพื่อเพิ่มความคิดเห็น
John Zabroski

21

ฉันมีปัญหานี้ที่ Git GUI และ SourceTree จัดการกับไฟล์ Java / JS เป็นไบนารีและทำให้ไม่เห็นความแตกต่าง

การสร้างไฟล์ชื่อ "attributes" ใน. git \ info โฟลเดอร์ที่มีเนื้อหาต่อไปนี้ช่วยแก้ปัญหาได้

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

หากคุณต้องการทำการเปลี่ยนแปลงนี้กับที่เก็บข้อมูลทั้งหมดคุณสามารถเพิ่มไฟล์แอททริบิวต์ในตำแหน่งต่อไปนี้ $ HOME / .config / git / attributes


1
นอกจากนี้ให้สังเกต<project-root>/.gitattributesไฟล์ซึ่งทำให้การเปลี่ยนแปลงใช้งานได้สำหรับผู้มีส่วนร่วมทั้งหมดและเฉพาะสำหรับโครงการที่เกี่ยวข้อง
jpaugh

การเพิ่ม* diffมีประโยชน์สำหรับฉัน: มันแสดงให้เห็นถึงความแตกต่างในไฟล์ทุกประเภท แต่ทางออกของคุณดีกว่าเพราะหลีกเลี่ยงการแสดง diff ที่ไม่จำเป็นในไฟล์ไบนารีขนาดใหญ่
Boolean_Type

ใช่ สิ่งนี้ช่วยได้!
WildCat

19

Git จะตรวจสอบว่ามันเป็นเลขฐานสองหากคุณมีหนึ่งบรรทัดที่ยาวเป็นพิเศษในไฟล์ข้อความของคุณ ฉันเลิกใช้สตริงยาว ๆ เปลี่ยนเป็นซอร์สโค้ดหลายบรรทัดและทันใดนั้นไฟล์ก็เปลี่ยนจากการเป็น 'ไบนารี' ไปเป็นไฟล์ข้อความที่ฉันเห็น (ใน SmartGit)

ดังนั้นอย่าพิมพ์ต่อไปทางด้านขวาจนเกินไปโดยไม่กดปุ่ม 'Enter' ในตัวแก้ไขของคุณมิฉะนั้น Git ในภายหลังจะคิดว่าคุณได้สร้างไฟล์ไบนารีแล้ว


1
นี่เป็นข้อมูลที่ถูกต้อง ฉันพยายามควบคุมแตกต่างจาก MySQL Dump (ไฟล์. sql) ที่มีขนาดใหญ่มาก แต่ git ถือว่ามันเป็นไฟล์ไบนารีแม้ว่ามันจะมีเพียงข้อมูล ASCII / UTF8 ก็ตาม เหตุผลก็คือเส้นนั้นยาวมาก (แทรกค่า (หนึ่ง), (สอง), (สาม), (... ), (3 ล้าน ... ) ;. แปลกสำหรับที่เก็บข้อมูลทุกคอม ไม่เพิ่มขึ้น 1.7gb แต่เพียง ~ 350mb บางที git กำลังบีบอัดไฟล์ "binary" ก่อนที่จะบันทึก
Alexandre T.

@AlexandreT Git ทำการบีบอัดไฟล์ blobs (โดยใช้ GZip, IIRC)
jpaugh

11

ฉันมีปัญหาเดียวกันนี้หลังจากแก้ไขไฟล์หนึ่งไฟล์ในโปรแกรมแก้ไขใหม่ ปรากฎว่าเครื่องมือแก้ไขใหม่ใช้การเข้ารหัสที่แตกต่าง (Unicode) กว่าโปรแกรมแก้ไขเก่าของฉัน (UTF-8) ดังนั้นฉันเพียงแค่บอกบรรณาธิการใหม่ของฉันให้บันทึกไฟล์ของฉันด้วย UTF-8 จากนั้น git แสดงการเปลี่ยนแปลงของฉันอย่างถูกต้องอีกครั้งและไม่เห็นว่าเป็นไฟล์ไบนารี

ฉันคิดว่าปัญหาเป็นเพียงการคอมไพล์ไม่ทราบวิธีการเปรียบเทียบไฟล์ประเภทการเข้ารหัสที่แตกต่างกัน ดังนั้นประเภทการเข้ารหัสที่คุณใช้จริง ๆ ไม่สำคัญตราบใดที่มันยังคงสอดคล้องกัน

ฉันไม่ได้ทดสอบ แต่ฉันแน่ใจว่าฉันจะยืนยันไฟล์ของฉันด้วยการเข้ารหัส Unicode ใหม่ครั้งต่อไปที่ฉันทำการเปลี่ยนแปลงไฟล์นั้นมันจะแสดงการเปลี่ยนแปลงอย่างถูกต้องและตรวจไม่พบว่าเป็นไบนารีเนื่องจาก จากนั้นจะเป็นการเปรียบเทียบไฟล์ที่เข้ารหัส Unicode สองไฟล์ไม่ใช่ไฟล์ UTF-8 กับไฟล์ Unicode

คุณสามารถใช้แอพเช่นNotepad ++เพื่อดูและเปลี่ยนประเภทการเข้ารหัสของไฟล์ข้อความได้อย่างง่ายดาย เปิดไฟล์ใน Notepad ++ และใช้เมนูการเข้ารหัสในแถบเครื่องมือ


1
Unicode ไม่ใช่การเข้ารหัส มันเป็นชุดอักขระและ UTF-8 เป็นหนึ่งในการเข้ารหัสของมันคือวิธีการเข้ารหัส Unicode codepoint
phuclv

1
วิธีนี้ไม่สามารถแก้ไขปัญหาได้เพียงหลีกเลี่ยง ปัญหาคือ git หรือเครื่องมือ diff ไม่รู้จักไฟล์ข้อความอย่างถูกต้องหรือไม่อนุญาตให้ผู้ใช้แทนที่พฤติกรรมของมัน
Preza8

6

ฉันมีปัญหาเดียวกัน ฉันพบเธรดเมื่อฉันค้นหาโซลูชันบน google แต่ฉันก็ยังไม่พบเบาะแสใด ๆ แต่ฉันคิดว่าฉันพบเหตุผลหลังจากเรียนตัวอย่างด้านล่างจะอธิบายเบาะแสของฉันอย่างชัดเจน

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

สำหรับตอนนี้ไฟล์ new.txt ถือเป็นไฟล์ข้อความ

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

คุณจะได้รับผลลัพธ์นี้

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

และลองสิ่งนี้

git diff -a

คุณจะได้รับด้านล่าง

    diff --git a/new.txt b/new.txt
    index fa49b07..9664e3f 100644
    --- a/new.txt
    +++ b/new.txt
    @@ -1 +1 @@
    -new file
    +newer text^@

5

เรามีกรณีนี้ที่ไฟล์. html ถูกมองว่าเป็นไบนารีทุกครั้งที่เราพยายามทำการเปลี่ยนแปลง uncool มากที่จะไม่เห็นความแตกต่าง บอกตามตรงฉันไม่ได้ตรวจสอบวิธีแก้ไขทั้งหมดที่นี่ แต่สิ่งที่ใช้ได้ผลกับเราคือ:

  1. ลบไฟล์ (จริง ๆ แล้วย้ายไปยังเดสก์ท็อปของฉัน) และgit deletionยอมรับ Git พูดว่าDeleted file with mode 100644 (Regular) Binary file differs
  2. เพิ่มไฟล์อีกครั้ง (จริง ๆ แล้วย้ายมันจากเดสก์ท็อปของฉันกลับเข้าไปในโครงการ) Git กล่าวว่าNew file with mode 100644 (Regular) 1 chunk, 135 insertions, 0 deletionsขณะนี้ไฟล์ถูกเพิ่มเป็นไฟล์ข้อความปกติ

นับจากนี้ไปการเปลี่ยนแปลงใด ๆ ที่ฉันทำในไฟล์จะถือเป็นข้อความทั่วไปที่แตกต่างกัน คุณสามารถกำจัดสิ่งเหล่านี้ (1, 2 และ 3 เป็นการเปลี่ยนแปลงที่เกิดขึ้นจริง) แต่ฉันอยากเห็นในอนาคตว่าฉันทำอะไร การบีบที่ 1 และ 2 จะแสดงการเปลี่ยนแปลงแบบไบนารี


คล้ายกับหนึ่งหรือสองไฟล์ (รวบรวมสำเร็จ) ไฟล์ cpp ที่ถูกพุชจาก VS แสดง Github gui เพื่อเปรียบเทียบหัวเราะ ไม่มีใครอยากจะบินไปบนระฆังในการแลกเปลี่ยนดิงดอง - VS ด้านหนึ่งบอกว่าเป็น Github และอีกด้านหนึ่ง Github บอกว่าเป็น VS :(
Laurie Stearn

4

ต่อคำตอบที่เป็นประโยชน์นี้คุณสามารถขอ Git โดยตรงว่าทำไมมันถือว่าไฟล์ในทางหนึ่ง:

cd directory/of/interest
file *

มันสร้างผลลัพธ์ที่มีประโยชน์เช่นนี้

$ 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

6
fileไม่ใช่คำสั่ง git มันเป็นชุดเครื่องมือที่แยกกันโดยสิ้นเชิงกับ git บน Windows มีเอกสารแสดงว่านี่คือสิ่งที่ git ใช้สำหรับการตรวจจับไฟล์ไบนารี?
Max

4

สิ่งนี้ยังเกิดขึ้น (บน Windows อย่างน้อย) โดยไฟล์ข้อความที่มีUTF-8 พร้อมการเข้ารหัสBOM การเปลี่ยนการเข้ารหัสเป็นUTF-8ปกติทำให้ Git เห็นไฟล์เป็น type = text ทันที


1

ฉันมีตัวอย่างที่.gitignoreมีสองครั้ง\r (carriage return) ตามจุดประสงค์

ไฟล์นั้นถูกระบุว่าเป็นไบนารีโดย git การเพิ่ม.gitattributesไฟล์ช่วย

# .gitattributes file
.gitignore diff

1
ทำงาน ฉันยังมีสองครั้งที่จะไม่สนใจไฟล์ "Icon \ r \ r" OS บางตัว ดีใจที่ได้ทราบสาเหตุรวมถึงการแก้ไข
hsandt

1

หากgit check-attr --all -- src/my_file.txtระบุว่าไฟล์ของคุณมีค่าสถานะเป็นไบนารีและคุณยังไม่ได้ตั้งเป็นในไบนารีตรวจสอบหามันใน.gitattributes/.git/info/attributes


0

เปลี่ยน Aux.js เป็นชื่ออื่นเช่น Sig.js

ทรีของแหล่งข้อมูลยังคงแสดงเป็นไฟล์ไบนารี แต่คุณสามารถจัดลำดับ (เพิ่ม) และดำเนินการได้


0

ฉันมีปัญหาที่คล้ายกันเมื่อฉันวางข้อความบางส่วนจากข้อความไบนารีคาฟคาซึ่งแทรกอักขระที่มองไม่เห็นและทำให้คอมไพล์คิดว่าไฟล์นั้นเป็นไบนารี

ผมพบว่าตัวละครที่กระทำผิดโดยการค้นหาไฟล์โดยใช้ [^ -~\n\r\t]+regex

  • [ จับคู่อักขระในชุดนี้
  • ^ จับคู่อักขระที่ไม่ได้อยู่ในชุดนี้
  • -~ จับคู่อักขระทั้งหมดจาก '' (เว้นวรรค) ถึง '~'
  • \n ขึ้นบรรทัดใหม่
  • \r รับคืนรถ
  • \t แถบ
  • ] ชุดปิด
  • + จับคู่อักขระเหล่านี้อย่างน้อยหนึ่งตัว

-2

ฉันใช้เวลาหลายชั่วโมงผ่านทุกอย่างในรายการนี้เพื่อพยายามหาสาเหตุว่าทำไมหนึ่งในโครงการทดสอบในโซลูชันของฉันจึงไม่เพิ่มการทดสอบใด ๆ ให้กับนักสำรวจ

มันเปิดออกในกรณีของฉันว่าอย่างใด (อาจเป็นเพราะการคอมไพล์ยากจนไม่ดีที่ไหนสักแห่ง) ที่ VS ได้สูญเสียการอ้างอิงโครงการทั้งหมด มันยังคงอยู่ในอาคาร แต่ฉันสังเกตเห็นว่ามันสร้างเพียงการพึ่งพา

จากนั้นฉันสังเกตเห็นว่ามันไม่ปรากฏในรายการการพึ่งพาดังนั้นฉันจึงลบและเพิ่มโครงการทดสอบอีกครั้งและการทดสอบทั้งหมดของฉันก็ปรากฏขึ้นในที่สุด


2
Visual Studio จริงๆไม่เกี่ยวข้องที่นี่
jpaugh
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.