ปิดการใช้งานการแปลง EOL ของ git


109

ฉันพยายามทำให้คอมไพล์ไม่เปลี่ยนการสิ้นสุดบรรทัดสำหรับการดำเนินการใด ๆ น่าเสียดายที่ดูเหมือนว่าจะทำเช่นนั้นไม่สำคัญอะไร ฉันได้ลดมันลงเป็นกรณีทดสอบต่อไปนี้ซึ่งมีกลไกต่างๆในการปิดใช้งานพฤติกรรมนี้มากที่สุดเท่าที่ฉันจะพบได้


  • เริ่มต้นด้วยสองเครื่อง (คอมพิวเตอร์ Windows = A, คอมพิวเตอร์ Linux = B)
  • ในทั้งสองเครื่อง: git config --global core.autocrlf false
  • บนทั้งสองเครื่อง: git config --global core.eol crlf(ในกรณีที่)

  • สร้างที่เก็บใหม่บน A. จากโฟลเดอร์ว่าง:
    • git init --shared(จากนั้นยกเลิกการซ่อน.gitไดเร็กทอรีที่สร้างขึ้น)
    • สร้างไฟล์ใหม่.gitignoreในที่เก็บ
    • สร้างไฟล์ใหม่.gitattributesในที่เก็บด้วยบรรทัดเดียว:* -text
    • git add .แล้วgit commit -m "initial commit"การทำงานรอบเช่นนี้
    • git branch master_recv
    • เพิ่มรีโมท
  • สร้างไฟล์ใหม่document.txtในที่เก็บที่มี CRLF
  • กระทำ: git add -Aแล้วgit commit -m "<something>"
  • โปรดทราบว่า A document.txtยังคงมี CRLF (และลบและรีเซ็ตโดย--hardส่งคืนเวอร์ชันที่ยังคงอยู่กับ CRLF)

  • SCP ไดเรกทอรีทั้งหมดไปยังคอมพิวเตอร์ B
  • เพิ่มไฟล์ใหม่new fileที่มี CRLF
  • กระทำ: git add -Aแล้วgit commit -m "<something>"
  • โปรดทราบว่า B's document.txtและ B new fileทั้งสองยังคงมี CRLF

  • ดึงหลักของ B ไปที่ A: git pull <remote> master:master_recv
  • A document.txtเปลี่ยนเป็น LF แล้ว ไฟล์ที่เพิ่มnew fileยังมี LF

ปัญหาจะไม่เกิดขึ้นหาก B เป็นเครื่อง Windows


ได้core.autocrlf เสมอรับเท็จ? ดูเหมือนว่าคุณจะมี\nจุดสิ้นสุดบรรทัดในที่เก็บของคุณแล้ว? นอกจากนี้ยังไม่มีการตั้งค่าการเปลี่ยนแปลง\nในพื้นที่เก็บข้อมูลของคุณไป\r\nในไดเรกทอรีการทำงานของคุณ
Edward Thomson

ไม่ได้ตั้งค่าไว้เสมอไป (เช่นเมื่อสร้าง repo ครั้งแรก) อย่างไรก็ตามไม่ควรมีการสิ้นสุดบรรทัด CR ใน repo อยู่แล้ว และอีกครั้งฉันไม่ต้องการให้มีการเปลี่ยนแปลงเกิดขึ้น
imallett

ฉันถามเพราะการตั้งค่าของคุณควรรักษาส่วนท้ายบรรทัดของคุณเป็น CRLF คุณช่วยโพสต์ไฟล์ในที่เก็บของคุณด้วย ID อ็อบเจ็กต์เพื่อแก้ไข (ยอมรับว่าน่ารำคาญ) ได้ไหม
Edward Thomson

@EdwardThomson หมายความว่าไง? repo ไม่เป็นสาธารณะ (เนื่องจากเครื่อง Linux ไม่ใช่) ฉันจะถือว่าคุณต้องการไฟล์ตัวอย่าง ดูแก้ไข
imallett

ใช่ฉันยอมรับว่าไฟล์นั้นมีการลงท้ายบรรทัด CRLF คุณช่วยชี้แจงสิ่งหนึ่งได้ไหม: คุณกล่าวว่า "บรรทัดใหม่ของเครื่อง windows เปลี่ยนเป็น CR!" แน่นอนว่านั่นเป็นการพิมพ์ผิดหรือคุณได้รับการสิ้นสุดบรรทัดการคืนสายการบินแบบ MacOS 9 จริงๆ?
Edward Thomson

คำตอบ:


78

ภายในโครงการของคุณควรมี.gitattributesไฟล์ โดยส่วนใหญ่แล้วควรมีลักษณะดังนี้ (หรือภาพหน้าจอนี้):

# Handle line endings automatically for files detected as text 
# and leave all files detected as binary untouched.
* text=auto

# Never modify line endings of our bash scripts
*.sh -crlf

#
# The above will handle all files NOT found below
#
# These files are text and should be normalized (Convert crlf => lf)
*.css           text
*.html          text
*.java          text
*.js            text
*.json          text
*.properties    text
*.txt           text
*.xml           text

# These files are binary and should be left untouched
# (binary is macro for -text -diff)
*.class         binary
*.jar           binary
*.gif           binary
*.jpg           binary
*.png           binary

เปลี่ยน* text=autoเป็น* text=falseปิดใช้งานการจัดการอัตโนมัติ (ดูภาพหน้าจอ )

แบบนี้:

ป้อนคำอธิบายภาพที่นี่

หากโปรเจ็กต์ของคุณไม่มีไฟล์. gitattributes การสิ้นสุดบรรทัดจะถูกกำหนดโดยคอนฟิกูเรชัน git ของคุณ ในการเปลี่ยนการกำหนดค่าคอมไพล์ของคุณให้ทำดังนี้:

ไปที่ไฟล์ config ในไดเร็กทอรีนี้:

1) C: \ ProgramData \ Git \ config

2) เปิดไฟล์ config ใน Notepad ++ (หรือโปรแกรมแก้ไขข้อความที่คุณต้องการ)

3) เปลี่ยน "autocrlf =" เป็น false

ป้อนคำอธิบายภาพที่นี่


33
เหตุใดจึงต้องใช้รูปภาพแทนแท็กโค้ด ไม่สะดวกมาก
Clint

34
เพราะฉันสามารถเพิ่มกล่องสีแดงขนาดใหญ่ในภาพเพื่อเน้นสิ่งต่างๆ
ยีน

25
การใช้* text=falseไม่ยกเลิกการตั้งค่าข้อความ: ปล่อยให้ข้อความตั้งค่าสตริงเป็นเท็จ สิ่งนี้มีผลเช่นเดียวกับการปล่อยให้ข้อความไม่ระบุ (ไม่ได้ยกเลิกการตั้งค่าโดยเฉพาะ) การใช้* -textจะช่วยให้การตั้งค่ายกเลิกการตั้งค่าพิเศษ การยกเลิกการตั้งค่าแอตทริบิวต์ข้อความบนเส้นทางจะบอกให้คอมไพล์ไม่พยายามแปลงปลายทางใด ๆ เมื่อเช็คอินหรือชำระเงิน
JustAMartin

ขอบคุณ @Gene สำหรับคำตอบนี้ สิ่งนี้ทำให้ฉันคลั่งไคล้มาตลอดทั้งวันและสิ่งนี้แก้ไขให้ฉันได้!
LeopardSkinPillBoxHat

9
ขออภัยที่พูดไม่ได้ขอบคุณสำหรับคำตอบนี้ ฉันเสียเวลาครึ่งวันเพื่อพบว่ามีคนทำตามคำแนะนำที่ทำให้เข้าใจผิด ตามที่ @JustAMartin ชี้ว่า* text=falseไม่มีผล โปรดแก้ไขคำตอบ!
Paul B.

57

วิธีง่ายๆอย่างหนึ่งคือ:

  • ตรวจสอบให้แน่ใจว่า core.autocrlf ถูกตั้งค่าเป็นเท็จสำหรับrepos ทั้งหมด :
    git config --global core.autocrlf false
  • โคลน repo ของคุณอีกครั้งและตรวจสอบว่าไม่มีการแปลง EOL
  • หรือตั้งแต่ Git 2.16 (Q1 2018)ให้เก็บ repo ปัจจุบันของคุณไว้และทำไฟล์git add --renormalize .

หากมีการแปลงโดยอัตโนมัตินั่นหมายความว่ามี.gitattributes core.eolคำสั่งอยู่ใน repo

ด้วยGit 2.8+ (มีนาคม 2016)ตรวจสอบว่ายังมีการแปลง eol ด้วย:

git ls-files --eol

4
แค่อย่าใช้autocrlfวันนี้! unsetted autocrlfเทียบเท่ากับfalse. คุณล้าหลังการเคลื่อนไหวที่ทันสมัยใน Git
Lazy Badger

1
ข้างต้นฉันได้ลองสิ่งนี้แล้ว (แม้ว่าจะไม่ใช่กับธงสากล) แต่ก็ไม่ได้ผล เวอร์ชัน git คือ1.8.5.2.
imallett

@IanMallett "ณ จุดนี้ดูเหมือนว่าเครื่อง Linux ยังคงมี CRLF อยู่": มันจะดำเนินการจนกว่าคุณจะทำให้เนื้อหาเป็นปกติอีกครั้งหรือโคลน (เหมือนที่คุณทำบน windows)
VonC

หากคุณกำลังพยายามทำสิ่งนี้สำหรับ repo เพียงรายการเดียวให้เรียกใช้git config core.autocrlf false- พูดถึงสิ่งนี้เพราะโดยทั่วไปแล้ว autocrlf ควรมีtrueไว้สำหรับ windows และinputสำหรับคนอื่น ๆ แต่บางครั้งคุณก็ต้องการบางสิ่งที่เฉพาะเจาะจงสำหรับกรณีขอบแปลก ๆ ในกรณีของฉันฉันได้ดาวน์โหลดไฟล์บางไฟล์และต้องการบันทึกการเปลี่ยนแปลงที่ทำเพื่อที่ฉันจะได้จำสิ่งที่ฉันทำไปได้ (ซึ่งต่างจากการติดตามการเปลี่ยนแปลงโค้ด) ฉันไม่รู้ว่าการลงท้ายบรรทัดมีความสำคัญหรือไม่ (และต้องการความแตกต่างเพื่อให้สมเหตุสมผลกับ "ของจริง") ดังนั้นฉันจึงปิดการใช้งาน autocrlf
กัปตันแมน

12

ฉันคิดออกแล้ว ดูเหมือนว่าโปรแกรม SCP กำลังแปลงจุดสิ้นสุดบรรทัด ฉันสังเกตเห็นสิ่งนี้เมื่อฉันพยายามสร้างไฟล์ที่มีส่วนท้าย LF โดยเจตนาจากนั้นสังเกตว่ามันปรากฏเป็น CRLF เมื่อดาวน์โหลด

เนื่องจากนี่เป็นทางออกสำหรับฉันฉันจึงยอมรับคำตอบนี้ แต่ผู้คนในอนาคตควรอ้างถึงคำตอบอื่น ๆ เพื่อหาวิธีแก้ปัญหาทั่วไป


1
จับได้ดีเจาะจงมากกว่าคำตอบของฉัน +1
VonC

4

จากgitattributes (5) Manual Pageหัวข้อ "Effects"

text

แอตทริบิวต์นี้เปิดใช้งานและควบคุม end-of-line normalization เมื่อไฟล์ข้อความถูกทำให้เป็นมาตรฐานการสิ้นสุดบรรทัดจะถูกแปลงเป็น LF ในที่เก็บ หากต้องการควบคุมลักษณะการสิ้นสุดบรรทัดที่ใช้ในไดเร็กทอรีการทำงานให้ใช้eolแอ็ตทริบิวต์สำหรับไฟล์เดียวและcore.eol ตัวแปรคอนฟิกูเรชันสำหรับไฟล์ข้อความทั้งหมด

Set

การตั้งค่าแอตทริบิวต์ข้อความบนเส้นทางจะเปิดใช้งาน end-of-line normalization และทำเครื่องหมายเส้นทางเป็นไฟล์ข้อความ การแปลง End-of-line เกิดขึ้นโดยไม่ต้องเดาประเภทเนื้อหา

Unset การยกเลิกการตั้งค่าแอตทริบิวต์ข้อความบนเส้นทางจะบอกให้ Git ไม่พยายามแปลงปลายทางใด ๆ เมื่อเช็คอินหรือชำระเงิน

core.autocrlfใน Git ใหม่ (1.7.2+) ไม่ได้ใช้core.eolและการตั้งค่าที่ถูกต้อง | การยกเลิกการตั้งค่าแอตทริบิวต์ข้อความถือเป็นวิธีที่เชื่อถือได้มากกว่า


1
ใน.gitattributesไฟล์ฉันได้ปิดการใช้งานทุกอย่างเป็นข้อความอย่างชัดเจนใช่ไหม? นอกจากนี้ฉันไม่เห็นตัวเลือกที่จะทำให้ไม่แปลง (แม้ว่าcrlfอาจจะไม่มีผล)?
imallett

8
สิ่งที่สำคัญที่มักจะได้รับสับสน - เพื่อล้างtextและป้องกันการแปลงใด ๆ ที่คุณควรตั้ง .gitattributes ไปและไม่ให้* -text ไม่ใช่ค่าที่ถูกต้องสำหรับแอตทริบิวต์ - git จะไม่รู้จักและจะกลับไปใช้การตั้งค่า autocrlf เริ่มต้นแทน นอกจากนี้หลังจากเปลี่ยนค่าแล้วคุณต้องสำรองไฟล์ทั้งหมดจาก repo ในเครื่องของคุณทำการคอมมิตจากนั้นกู้คืนไฟล์ด้วย end-of-line ที่ถูกต้องตามที่คุณต้องการและคอมมิตกลับ จากนั้นส่วนท้ายของบรรทัดของคุณจะไม่ถูกแก้ไขโดย git อีกต่อไป * text=falsefalsetexttext
JustAMartin

2

นี่คือวิธีที่คุณทำสำหรับ repo เดียว

สร้างไฟล์.gitattributesที่ root ของ repo โดยมีบรรทัดนี้อยู่

* -text

แค่นั้นแหละ. นี่คือสัญลักษณ์แทนที่ตรงกับไฟล์ทั้งหมดโดยบอกให้ git ยกเลิกการตั้งค่าแอตทริบิวต์ข้อความ ซึ่งหมายความว่า git ถือว่าไฟล์ทั้งหมดเป็นไบนารีดังนั้นจึงไม่ทำการแปลงบรรทัดสิ้นสุดใด ๆ

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