กลยุทธ์การจัดการ CRLF (carriage return, line line) ที่ดีที่สุดกับ Git คืออะไร?


598

ฉันลองส่งไฟล์ที่มีบรรทัดสิ้นสุด CRLF แต่มันล้มเหลว

ผมใช้เวลาวันทำงานทั้งบนคอมพิวเตอร์ที่ใช้ Windows ของฉันพยายามกลยุทธ์ที่แตกต่างและถูกดึงออกมาเกือบจะหยุดการพยายามที่จะใช้ Git และแทนที่จะพยายามMercurial

โปรดแบ่งปันแนวทางปฏิบัติที่ดีที่สุดเพียงข้อเดียวต่อคำตอบ

คำตอบ:


753

เกือบสี่ปีหลังจากถามคำถามนี้ในที่สุดฉันก็ได้พบคำตอบที่ทำให้ฉันพอใจอย่างสมบูรณ์ !

ดูรายละเอียดในGitHub: ความช่วยเหลือของแนวทางในการ จัดการกับปลายสาย

Git อนุญาตให้คุณตั้งค่าคุณสมบัติการสิ้นสุดบรรทัดสำหรับ repo โดยตรงโดยใช้แอททริบิวข้อความใน .gitattributesไฟล์ ไฟล์นี้มีความมุ่งมั่นใน repo และแทนที่การcore.autocrlfตั้งค่าช่วยให้คุณมั่นใจได้ว่าพฤติกรรมที่สอดคล้องกันสำหรับผู้ใช้ทั้งหมดโดยไม่คำนึงถึงการตั้งค่า git ของพวกเขา

และด้วยเหตุนี้

ข้อดีของการตั้งค่านี้คือการตั้งค่าการสิ้นสุดบรรทัดของคุณเดินทางไปกับที่เก็บข้อมูลของคุณแล้วและคุณไม่ต้องกังวลว่าผู้ทำงานร่วมกันจะมีการตั้งค่าระดับโลกที่เหมาะสมหรือไม่

นี่คือตัวอย่างของ.gitattributesไฟล์

# Auto detect text files and perform LF normalization
*        text=auto

*.cs     text diff=csharp
*.java   text diff=java
*.html   text diff=html
*.css    text
*.js     text
*.sql    text

*.csproj text merge=union
*.sln    text merge=union eol=crlf

*.docx   diff=astextplain
*.DOCX   diff=astextplain

# absolute paths are ok, as are globs
/**/postinst* text eol=lf

# paths that don't start with / are treated relative to the .gitattributes folder
relative/path/*.txt text eol=lf

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

เมื่อคุณสร้างหรือปรับของคุณ.gitattributesคุณควรดำเนินการครั้งหนึ่งและสำหรับทุกปลายสายอีกครั้งฟื้นฟู

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

ในที่สุด, Mind the End of Your Lineจะให้ข้อมูลพื้นฐานเพิ่มเติมและอธิบายว่า Git มีการพัฒนาในเรื่องนี้อย่างไร ฉันพิจารณาการอ่านที่จำเป็นนี้

คุณอาจมีผู้ใช้ในทีมของคุณที่ใช้ EGit หรือ JGit (เครื่องมือเช่น Eclipse และ TeamCity ใช้พวกเขา) เพื่อยอมรับการเปลี่ยนแปลงของพวกเขา ถ้าอย่างนั้นคุณก็โชคไม่ดีอย่างที่ @gatinueta อธิบายไว้ในความคิดเห็นของคำตอบนี้:

การตั้งค่านี้จะไม่ทำให้คุณพึงพอใจหากคุณมีคนทำงานกับ Egit หรือ JGit ในทีมของคุณเนื่องจากเครื่องมือเหล่านั้นจะไม่สนใจ. gitattributes และตรวจสอบไฟล์ CRLF อย่างมีความสุข https://bugs.eclipse.org/bugs/show_bug.cgi? id = 342372

เคล็ดลับอย่างหนึ่งก็คือให้พวกเขาส่งมอบการเปลี่ยนแปลงในลูกค้ารายอื่น SourceTree ทีมของเรากลับชอบเครื่องมือนั้นต่อ EGIT ของ Eclipse สำหรับกรณีการใช้งานมากมาย

ใครบอกว่าซอฟต์แวร์นั้นง่าย : - /


7
สนใจที่จะแชร์ Windows .gitattributesหรือไม่
พันเอก Panic

คุณจะเห็นว่า.gitattributesGitHub สำหรับ Windows แนะนำอะไรให้กับโครงการของคุณ ฉันติดตั้ง GitHub สำหรับ Windows เริ่มเวอร์ชัน GUI และไม่พบตัวเลือกที่เกี่ยวข้องกับ.gitattributesคำแนะนำ
JLDiaz

4
การตั้งค่านี้จะไม่ทำให้คุณพึงพอใจอย่างสมบูรณ์หากคุณมีคนทำงานกับ Egit ในทีมของคุณเนื่องจาก egit จะเพิกเฉยต่อ. gitattributes และตรวจสอบในไฟล์ CRLF อย่างมีความสุขbugs.eclipse.org/bugs/show_bug.cgi?id=342372
gatinueta

19
สำหรับ Windows ฉันมักจะตั้งทั่วโลกcore.autocrlf = false- ฉันชอบ LF ทุกที่ แต่เครื่องมือ Windows บางตัวเช่น Visual Studio ยืนยันในตอนจบของ CRLF ในไฟล์บางไฟล์ การไม่ต้องปิดปลายสายเป็นตัวเลือกที่ปลอดภัยที่สุด หากคุณรู้ว่าคุณกำลังทำอะไรฉันอาจใช้core.autocrlf = inputและสร้างข้อยกเว้นสำหรับโครงการบน Windows ที่คุณรู้ว่ามีความอ่อนไหวต่อการสิ้นสุดของบรรทัด ดังที่คนอื่น ๆ ชี้ให้เห็นเครื่องมือแก้ไขข้อความที่เหมาะสมทุกประเภทสนับสนุนการจบ LF ในตอนนี้ จริง ๆ แล้วฉันคิดว่าcore.autocrlf = trueอาจทำให้เกิดปัญหามากกว่าที่ป้องกันได้
เอเดรีย

1
@gatinueta จะเจาะจงมากขึ้นมันเป็นปัญหาของ JGit ความหมาย TeamCity ซึ่งใช้ JGit ตรงข้ามละเว้น. gitattributes
sdds

122

อย่าแปลงจุดสิ้นสุดของบรรทัด มันไม่ใช่หน้าที่ของ VCS ในการตีความข้อมูล - เพียงแค่เก็บและจัดทำข้อมูล เครื่องมือแก้ไขข้อความที่ทันสมัยทุกตัวสามารถอ่านการจบบรรทัดทั้งสองประเภทได้


25
หนุน หากคุณมีปัญหากับการวางสายที่ไม่สอดคล้องกันทางออกที่ดีที่สุดคือการตะโกนใครก็ตามที่ใช้การตั้งค่าเครื่องมือแก้ไขที่ไม่ถูกต้องจนกว่าจะแก้ไข

136
ไม่เห็นด้วย ฟีดแบบดั้งเดิมบนทุกแพลตฟอร์มนั้นสะดวกสบาย
Jonas Byström

25
Visual Studio เป็น PITA เมื่อพูดถึงสิ่งอื่นนอกเหนือจาก CRLF
Brett Ryan

32
Git มีตัวเลือกที่จะไม่แปลงปลายสายมันเป็น autocrlf = false และถ้าคุณไม่ทำการพัฒนาข้ามแพลตฟอร์มเช่นพูดว่า Mono ดีที่สุดเป็น false เมื่อทำงานบน Windows และตั้งค่าเป็นจริงถ้าคุณจะพัฒนาโอเพ่นซอร์ส สำหรับโมโน
Chris Nicola

24
ปัญหาของการสิ้นสุดบรรทัดคือการคำนวณต่างที่ถูกต้อง ดังนั้นคำตอบนั้นผิดและทำให้เข้าใจผิด
cos

84

คุณมักจะต้องการautocrlf=inputเว้นแต่คุณจะรู้ว่าคุณกำลังทำอะไรอยู่

บริบทเพิ่มเติมด้านล่าง:

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

ย่อหน้าข้างต้นเดิมถูกดึงออกมาจากกระทู้ใน gmane.org แต่หลังจากลงไปแล้ว


31
ทำไมมันถึงเป็น "สิ่งที่ถูกต้อง"?
Artem Tikhomirov

35
core.autocrlf = true เป็นความคิดที่แย่มาก ฉันไม่มีปัญหากับตัวเลือกนั้นรวมทั้งคุณต้องจำไว้ว่าเมื่อใดก็ตามที่คุณโคลนที่เก็บ
Luís Oliveira

28
อย่าใช้ autocrlf = true เว้นแต่คุณจะรู้ว่าคุณกำลังทำอะไรอยู่ หากคุณพัฒนาใน DOS / Win แล้ว autocrlf = false จะทำให้ตอนจบเหมือนกันระหว่าง repo ระยะไกลและท้องถิ่นและเป็นตัวเลือกที่ดีที่สุดในเกือบทุกสถานการณ์
Chris Nicola

13
@Chris - จะเกิดอะไรขึ้นหากนักพัฒนาของคุณมีโครงการ windows และหลายแพลตฟอร์มที่นักพัฒนาหลายแพลตฟอร์มทำงานบน OSX หรือ Linux ตัวเลือกที่ดีที่สุดควรเป็น autocrlf = true หรือไม่
Brett Ryan

20
โหวตขึ้นกับการจอง ย่อหน้าเบื้องต้นไม่ช่วยเหลือ core.autocrlf=inputเป็นคำตอบที่ยอมรับได้ สำหรับกรณีการใช้งานส่วนใหญ่core.autocrlf=trueและcore.autocrlf=falseมีความกระตือรือร้นสูงเกินไป (... ในทางตรงกันข้าม "Git สำหรับ Windows" ควรจริงๆได้มาพร้อมกับ "ชำระเงินตามที่เป็นกระทำ Unix สไตล์ปลายสาย" (กล่าวคือcore.autocrlf=input) เป็นกลยุทธ์การขึ้นบรรทัดใหม่เริ่มต้น มันไม่ได้ ดังนั้นที่นี่เราอยู่ที่นี่ - ใน frickin '2015 - ยังคงถกเถียงกันอย่างนี้
เซซิลแกงกะหรี่

58

สองกลยุทธ์ทางเลือกเพื่อให้สอดคล้องกันกับจุดสิ้นสุดบรรทัดในสภาพแวดล้อมแบบผสม (Microsoft + Linux + Mac):

A. ส่วนกลางต่อการตั้งค่าที่เก็บทั้งหมด

1) แปลงทั้งหมดเป็นรูปแบบเดียว

find . -type f -not -path "./.git/*" -exec dos2unix {} \;
git commit -a -m 'dos2unix conversion'

2) ตั้งค่าcore.autocrlfเป็นinputบน Linux / UNIX หรือtrueบน MS Windows (พื้นที่เก็บข้อมูลหรือทั่วโลก)

git config --global core.autocrlf input

3) [ไม่บังคับ] ตั้งค่าcore.safecrlfเป็นtrue(เพื่อหยุด) หรือwarn(เพื่อร้องเพลง :) เพื่อเพิ่มการป้องกันพิเศษหากการแปลงบรรทัดขึ้นบรรทัดใหม่กลับรายการจะส่งผลให้ไฟล์เดียวกัน

git config --global core.safecrlf true


B. หรือตามการตั้งค่า Repository

1) แปลงทั้งหมดเป็นรูปแบบเดียว

find . -type f -not -path "./.git/*" -exec dos2unix {} \;
git commit -a -m 'dos2unix conversion'

2) เพิ่ม.gitattributesไฟล์ลงในที่เก็บของคุณ

echo "* text=auto" > .gitattributes
git add .gitattributes
git commit -m 'adding .gitattributes for unified line-ending'

ไม่ต้องกังวลกับไฟล์ไบนารีของคุณ - Git ควรฉลาดพอสำหรับไฟล์


เพิ่มเติมเกี่ยวกับตัวแปร safecrlf / autocrlf


5
วิธีการทั่วโลก == ตั้งค่าและลืม repos ทั้งหมดต่อ repo == ไม่ต้องการให้คนอื่นเปลี่ยนการกำหนดค่าทั่วโลก
lukmdo

4
dos2unixเป็นเครื่องมือบรรทัดคำสั่งที่ขึ้นอยู่กับระบบที่คุณอาจต้องติดตั้งเพิ่มเติม
lukmdo

2
พวกเขาไม่ได้เป็นเอกสิทธิ์คุณสามารถใช้ทั้งสองวิธีพร้อมกัน นอกจากนี้โปรดระมัดระวังเมื่อใช้dos2unix- มีความเสี่ยงที่จะเกิดความเสียหาย.git/indexและเราไม่จำเป็นต้องใช้มันกับทุกไฟล์ จะเป็นการดีกว่าหากใช้สิ่งที่ต้องการfind ./ -name "*.html"และระบุไฟล์ที่คุณต้องการใช้กับมัน
cregox

6
คำเตือน: ก่อนใช้งานfindบรรทัดให้ระวัง: สิ่งdos2unixที่มาพร้อมกับ Git สำหรับ Windows นั้นมีพฤติกรรมแปลก ๆ (IMO idiotic และอันตราย) โดยไม่มีข้อโต้แย้ง: แทนที่จะเปลี่ยนเป็น UNIX มันจะสลับรูปแบบขึ้นบรรทัดใหม่ (DOS <-> UNIX )
leonbloy

2
และอีกคำเตือน: ห้าม DOS2UNIX โฟลเดอร์. git ของคุณ แค่พูด.
hakre

10

ลองตั้งค่าตัวเลือกการกำหนดค่าcore.autocrlf trueยังได้ดูที่core.safecrlfตัวเลือก

ที่จริงดูเหมือนว่าcore.safecrlfอาจมีการตั้งค่าในพื้นที่เก็บข้อมูลของคุณเพราะ (เน้นเหมือง):

ถ้ากรณีนี้ไม่ได้สำหรับการตั้งค่าปัจจุบันของ core.autocrlf, คอมไพล์จะปฏิเสธไฟล์

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

ในที่สุดฉันรู้สึกว่าคำแนะนำเพียง "ใช้สิ่งที่คุณได้รับ" และใช้ LF ที่ถูกยกเลิกบรรทัดบน Windows จะทำให้เกิดปัญหามากกว่าที่จะแก้ไข Git มีตัวเลือกด้านบนเพื่อพยายามจัดการกับจุดสิ้นสุดของเส้นอย่างสมเหตุสมผลดังนั้นจึงเหมาะสมที่จะใช้


1
จะดีกว่าไหมถ้าใช้การตั้งค่าที่เก็บกว้างผ่านไฟล์. gitattributes เพียงแค่สงสัยว่า: มันไม่สะดวกที่จะบังคับให้ผู้ใช้ทุกคนดูแลการตั้งค่าการสิ้นสุดบรรทัดของเขาบนเครื่องของเขา ... หรือมีข้อเสียอื่น ๆ ?
trainoasis

10

การใช้core.autocrlf=falseหยุดไฟล์ทั้งหมดไม่ให้ทำเครื่องหมายอัปเดตทันทีที่ฉันเช็กเอาต์ไฟล์เหล่านั้นในVisual Studio 2010ของฉันโครงการสมาชิกอีกสองคนของทีมพัฒนากำลังใช้ระบบ Windows ด้วยดังนั้นสภาพแวดล้อมแบบผสมไม่ได้เล่นอยู่ แต่การตั้งค่าเริ่มต้นที่มาพร้อมกับที่เก็บจะทำเครื่องหมายไฟล์ทั้งหมดว่าอัปเดตทันทีหลังจากการโคลน

ฉันเดาว่าสิ่งที่สำคัญที่สุดคือการค้นหาการตั้งค่า CRLF ที่เหมาะกับสภาพแวดล้อมของคุณ โดยเฉพาะอย่างยิ่งเนื่องจากในที่เก็บอื่น ๆ บนการตั้งค่ากล่อง Linux ของเราautocrlf = trueให้ผลลัพธ์ที่ดีกว่า

มากกว่า 20 ปีต่อมาและเรายังคงต้องเผชิญกับความขัดแย้งที่ไม่สิ้นสุดระหว่างระบบปฏิบัติการ ... เศร้า


31
@ orange80 ความแตกต่างเป็นเรื่องที่โชคร้าย แต่ก็ไม่มีเหตุผลที่จะเรียกว่าความผิดพลาดของ Windows LF-only ทำให้รู้สึกจากมุมมองที่เรียบง่ายบางที; แต่ CRLF สมเหตุสมผลมากขึ้นตามความหมายของ CR และ LF "Carriage return" หมายถึงการกลับไปที่จุดเริ่มต้นของบรรทัด; "ตัวดึงข้อมูลบรรทัด" หมายถึงการย้ายลงไปที่บรรทัดถัดไปโดยตรงแทนที่จะไปที่จุดเริ่มต้นของบรรทัดถัดไป จากมุมมองทางความหมาย Windows มีความถูกต้องมากขึ้นในการมีทั้ง: ย้ายกลับไปที่จุดเริ่มต้น (CR) และจากนั้นลงหนึ่งบรรทัด (LF)
Ryan Lundy

40
@ Kyralessa "ถูกต้องมากกว่า" ในการทำท่าว่าคอมพิวเตอร์ยังคงเป็นเครื่องพิมพ์ดีดซึ่งไม่ใช่ btw การคงความคล้ายคลึงของเครื่องพิมพ์ดีดนั้นไม่สมเหตุสมผลเลยเพราะสิ่งนี้ไม่ใช่สิ่งที่ผู้ใช้จะต้องเผชิญและตัวละครสองตัวแทนที่จะเป็นตัวเดียวนั้นไม่มีจุดหมาย
jpswain

1
ปาร์ตี้นี้มาถึงไม่กี่ปีที่ผ่านมา แต่คุณไม่สนใจความจริงที่ว่า CR และ LF เป็นเครื่องมือวางตำแหน่งเคอร์เซอร์ "CR" อาจเป็น "Cursor Return" ณ จุดนี้ในประวัติศาสตร์ หากฉันต้องการให้เคอร์เซอร์กลับไปที่จุดเริ่มต้นของบรรทัดฉันจะบอกให้แอปพลิเคชันทำเช่นนั้น มิฉะนั้นจะต้องอยู่ที่ฉันใส่
EKW

2
นอกจากนี้หาก CRLF "ถูกต้องมากขึ้น" เพราะบรรทัดใหม่ของ textline นั้นเป็นทั้ง "ย้ายหนึ่งแถวลง" และ "ย้ายไปยังจุดเริ่มต้นของบรรทัด" ก็จะตามมาด้วยว่ามีเพียง CR เท่านั้นที่จะทำให้โปรแกรมแก้ไขข้อความเขียนทับบรรทัดด้วย บรรทัดต่อไปนี้ ฉันรู้ว่าไม่มีบรรณาธิการที่สนับสนุนสิ่งนี้จริง ๆ แล้วหมายความว่าไม่จำเป็นต้องแสดงทั้ง CRLF และ CR เป็นสิ่งที่แตกต่างกัน
avl_sweden

@avl_sweden มันเป็นพฤติกรรมที่พบบ่อยมากก่อนที่ DOS และเนื่องจาก Microsoft คิดว่าการใช้งานร่วมกันได้เป็นสิ่งสำคัญ นอกจากนี้ยังเป็นวิธีมาตรฐานในสหรัฐอเมริกา (เช่น pere ASA) - ISO อนุญาตทั้ง CR + LF และ LF (อีกครั้ง DOS เป็นไปตามมาตรฐาน); ในทั้งสองกรณีตั้งแต่อายุหกสิบเศษ Multics (Unix precursor) รองรับ CR สำหรับตัวหนา / การโจมตี ปัจจุบันแอปพลิเคชั่นจำนวนมากในปัจจุบัน (รวมถึงฟีเจอร์ "แยกจากบรรทัด" ของ. NET) มองหาหนึ่งในสาม (lone CR, lone LF, CRLF) ทั้งสามและปฏิบัติต่อพวกเขาเป็น end-line อย่างไรก็ตามแอปพลิเคชั่นหลายตัวยังสับสนโดยการวางสายแบบผสมในไฟล์
Luaan

7

นี่คือสองตัวเลือกสำหรับผู้ใช้ WindowsและVisual Studio ที่ใช้รหัสร่วมกับผู้ใช้MacหรือLinux สำหรับคำอธิบายเพิ่มเติมให้อ่านคู่มือ gitattributesคู่มือ

* text = auto

ใน.gitattributesไฟล์repo ของคุณเพิ่ม:

*   text=auto

นี่จะทำให้ไฟล์ทั้งหมดเป็นปกติด้วย LFสิ้นสุดบรรทัดใน repo

และขึ้นอยู่กับระบบปฏิบัติการของคุณ ( core.eolการตั้งค่า) ไฟล์ในแผนผังการทำงานจะถูกทำให้เป็นมาตรฐานLFสำหรับระบบที่ใช้ Unix หรือCRLFระบบ Windows

นี่คือการกำหนดค่าที่Microsoft .NET repos ใช้

ตัวอย่าง:

Hello\r\nWorld

จะถูกทำให้เป็นมาตรฐานใน repo เสมอเช่น:

Hello\nWorld

เมื่อทำการเช็คเอาต์แผนผังการทำงานใน Windows จะถูกแปลงเป็น:

Hello\r\nWorld

เมื่อชำระเงินต้นไม้ทำงานใน Mac จะถูกปล่อยเป็น:

Hello\nWorld

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

core.autocrlf = จริง

หากtextไม่ได้ระบุใน.gitattributesไฟล์ Git จะใช้core.autocrlfตัวแปรการกำหนดค่าเพื่อพิจารณาว่าควรแปลงไฟล์นั้นหรือไม่

สำหรับผู้ใช้ Windows git config --global core.autocrlf trueเป็นตัวเลือกที่ดีเพราะ:

  • ไฟล์จะถูกทำให้เป็นLFบรรทัดสุดท้ายที่สิ้นสุดเมื่อเพิ่มลงใน repo เท่านั้น หากมีไฟล์ที่ไม่ได้รับการทำให้เป็นมาตรฐานใน repo การตั้งค่านี้จะไม่แตะต้อง
  • ไฟล์ข้อความทั้งหมดจะถูกแปลงเป็นCRLFจุดสิ้นสุดบรรทัดในไดเรกทอรีการทำงาน

ปัญหาของวิธีนี้คือ:

  • หากคุณเป็นผู้ใช้ Windows ด้วยautocrlf = inputคุณจะเห็นไฟล์หลายไฟล์ที่LFลงท้ายด้วยบรรทัด ไม่ใช่อันตรายสำหรับคนอื่น ๆ ในทีมเพราะความมุ่งมั่นของคุณจะยังคงเป็นมาตรฐานด้วยการLFจบบรรทัด
  • หากคุณเป็นผู้ใช้ Windows ด้วยcore.autocrlf = falseคุณจะเห็นกลุ่มไฟล์ที่มีการLFสิ้นสุดบรรทัดและคุณอาจแนะนำไฟล์ที่มีการCRLFลงท้ายบรรทัดลงใน repo
  • ผู้ใช้ส่วนใหญ่ใช้ Mac autocrlf = inputและอาจได้รับไฟล์ที่มีCRLFตอนจบไฟล์อาจจะมาจากผู้ใช้ Windows core.autocrlf = falseด้วย

1
คำสั่งของคุณสำหรับผู้ใช้ Windows git config --global core.autocrl trueกล่าวว่า git config --global core.autocrlf trueคุณหมายถึง
JellicleCat

6

--- UPDATE 3 --- (ไม่ขัดแย้งกับ UPDATE 2)

พิจารณากรณีที่ผู้ใช้ windows ชอบทำงานCRLFและผู้ใช้ linux / mac ชอบทำงานกับLFไฟล์ข้อความ ให้คำตอบจากมุมมองของผู้ดูแลพื้นที่เก็บข้อมูล :

สำหรับฉันกลยุทธ์ที่ดีที่สุด (ปัญหาที่ต้องแก้ไขน้อยกว่า) คือ: เก็บไฟล์ข้อความทั้งหมดไว้ด้วยLFคอมไพล์ repo ภายในแม้ว่าคุณจะทำงานในโครงการหน้าต่างเท่านั้น จากนั้นให้อิสระกับลูกค้าในการทำงานในรูปแบบบรรทัดสุดท้ายของการตั้งค่าของพวกเขาหากพวกเขาเลือกcore.autocrlfค่าคุณสมบัติที่จะเคารพกลยุทธ์ของคุณ (LF on repo)ในขณะที่จัดเตรียมไฟล์สำหรับการส่งมอบ

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

  • การเพิ่มไฟล์ข้อความสำหรับการคอมมิชชัน ( การจัดเตรียมไฟล์) นั้นเหมือนกับการคัดลอกไฟล์ไปยังอีกที่หนึ่งใน.git/ไดเรกทอรีย่อยที่มีการสิ้นสุดบรรทัดที่แปลง (ขึ้นอยู่กับcore.autocrlfค่าของการกำหนดค่าไคลเอนต์ของคุณ) ทั้งหมดนี้ทำในท้องถิ่น
  • การตั้งค่าcore.autocrlfเป็นเหมือนการให้คำตอบสำหรับคำถาม (คำถามเดียวกันที่แน่นอนในทุกระบบปฏิบัติการ):
    • "ควร git-client a. แปลง LF-to-CRLF เมื่อทำการเช็คเอาท์ (ดึง) การเปลี่ยนแปลง repo จากระยะไกลหรือb. แปลง CRLF-to-LF เมื่อเพิ่มไฟล์สำหรับการส่ง? " และคำตอบที่เป็นไปได้ (ค่า) คือ:
    • false:" ไม่ทำสิ่งใด ๆข้างต้น ",
    • input:" ทำแค่ข "
    • true: "ทำและและ b "
    • โปรดทราบว่าไม่มี " ทำเพียง "

โชคดี

  • ค่าเริ่มต้นของไคลเอนต์ git (windows core.autocrlf: true:, linux / mac:) core.autocrlf: falseจะเข้ากันได้กับกลยุทธ์LF-only-repo
    ความหมาย : ไคลเอนต์ windows จะโดยค่าเริ่มต้นจะแปลงเป็น CRLF เมื่อตรวจสอบพื้นที่เก็บข้อมูลและแปลงเป็น LF เมื่อทำการเพิ่ม ตามค่าเริ่มต้นแล้วลูกค้าของ linux จะไม่ทำการแปลงใด ๆ ตามหลักวิชานี้จะช่วยให้ repo ของคุณเพียงอย่างเดียว

น่าเสียดาย:

  • อาจมีไคลเอ็นต์ GUI ที่ไม่เคารพcore.autocrlfค่าgit
  • อาจมีคนที่ไม่ได้ใช้คุณค่าที่จะเคารพกลยุทธ์ lf-repo ของคุณ เช่นพวกเขาใช้core.autocrlf=falseและเพิ่มไฟล์ด้วย CRLF สำหรับการกระทำ

ในการตรวจจับไฟล์ข้อความที่ไม่ใช่ lf โดย ASAP ที่ได้รับมอบหมายจากไคลเอนต์ข้างต้นคุณสามารถทำตามสิ่งที่อธิบายไว้ใน --- update 2 ---: ( git grep -I --files-with-matches --perl-regexp '\r' HEAD, สำหรับลูกค้าที่คอมไพล์โดยใช้: --with-libpcreflag)

และนี่คือการจับ: ฉันในฐานะผู้ดูแล repo เก็บไว้git.autocrlf=inputเพื่อให้ฉันสามารถแก้ไขไฟล์ที่มีข้อผิดพลาดเพียงแค่เพิ่มไฟล์เหล่านั้นอีกครั้งสำหรับคอมมิท และฉันให้ข้อความกระทำ: "แก้ไขไฟล์มุ่งมั่นผิด"

เท่าที่.gitattributesถูกปกปิดไว้ ฉันไม่นับเพราะมีลูกค้า UI มากขึ้นที่ไม่เข้าใจ ฉันใช้มันเพื่อให้คำแนะนำสำหรับไฟล์ข้อความและไบนารีเท่านั้นและอาจตั้งค่าสถานะไฟล์พิเศษบางอย่างที่ทุกแห่งควรจะรักษาจุดสิ้นสุดของบรรทัดไว้เหมือนกัน:

*.java          text !eol # Don't do auto-detection. Treat as text (don't set any eol rule. use client's)
*.jpg           -text     # Don't do auto-detection. Treat as binary
*.sh            text eol=lf # Don't do auto-detection. Treat as text. Checkout and add with eol=lf
*.bat           text eol=crlf # Treat as text. Checkout and add with eol=crlf

คำถาม: แต่ทำไมเราถึงสนใจในกลยุทธ์การจัดการบรรทัดใหม่ทั้งหมด?

คำตอบ:เพื่อหลีกเลี่ยงการเปลี่ยนตัวอักษรกระทำเดียวปรากฏเป็นการเปลี่ยนแปลง 5000 บรรทัดเพียงเพราะลูกค้าที่ดำเนินการเปลี่ยนแปลงอัตโนมัติแปลงไฟล์เต็มจาก crlf เป็น lf (หรือตรงกันข้าม) ก่อนที่จะเพิ่มมันสำหรับการกระทำ นี้อาจจะค่อนข้างเจ็บปวดเมื่อมีการแก้ปัญหาความขัดแย้งที่เกี่ยวข้อง หรือในบางกรณีอาจเป็นสาเหตุของความขัดแย้งที่ไม่สมเหตุสมผล


--- ปรับปรุง 2 ---

dafaults ของไคลเอนต์ git จะทำงานในกรณีส่วนใหญ่ แม้ว่าคุณจะมีเพียง windows client เท่านั้น แต่ลูกค้า linux เท่านั้นหรือทั้งสอง เหล่านี้คือ:

  • windows: core.autocrlf=trueหมายถึงแปลงสายเป็น CRLF เมื่อชำระเงินและแปลงเป็น LF เมื่อเพิ่มไฟล์
  • linux: core.autocrlf=inputหมายถึงไม่ต้องแปลงบรรทัดในการชำระเงิน (ไม่จำเป็นต้องเนื่องจากไฟล์ที่คาดว่าจะผูกมัดกับ LF) และแปลงบรรทัดเป็น LF (ถ้าจำเป็น) เมื่อเพิ่มไฟล์ ( - update3 - : ดูเหมือนว่านี่เป็นfalseค่าเริ่มต้น แต่ก็ใช้ได้อีกครั้ง)

สามารถตั้งค่าคุณสมบัติในขอบเขตที่แตกต่างกัน ฉันขอแนะนำให้ตั้งค่าอย่างชัดเจนใน--globalขอบเขตเพื่อหลีกเลี่ยงปัญหา IDE บางอย่างที่อธิบายไว้ในตอนท้าย

git config core.autocrlf
git config --global core.autocrlf
git config --system core.autocrlf
git config --local core.autocrlf
git config --show-origin core.autocrlf

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

ตอนนี้สำหรับกรณีพิเศษของไฟล์ (เช่น*.bat *.sh) ที่คุณต้องการให้พวกเขาเช็คเอาท์ด้วย LF หรือ CRLF คุณสามารถใช้.gitattributes

สรุปการปฏิบัติที่ดีที่สุดสำหรับฉันคือ:

  • ตรวจสอบให้แน่ใจว่าไฟล์ที่ไม่ใช่ไบนารีทุกไฟล์ถูกกำหนดด้วย LF บน git repo (พฤติกรรมเริ่มต้น)
  • ใช้คำสั่งนี้เพื่อให้แน่ใจว่าไม่มีไฟล์ที่ถูกคอมมิตด้วย CRLF: git grep -I --files-with-matches --perl-regexp '\r' HEAD( หมายเหตุ:บนไคลเอนต์ windows ทำงานผ่านgit-bashไคลเอนต์ linux เท่านั้นและต่อเมื่อคอมไพล์โดยใช้--with-libpcreใน./configure )
  • หากคุณพบไฟล์ดังกล่าวโดยเรียกใช้คำสั่งข้างต้นแก้ไขให้ถูกต้อง สิ่งนี้เกี่ยวข้องกับ (อย่างน้อยใน linux):
    • set core.autocrlf=input( --- อัปเดต 3 - )
    • เปลี่ยนไฟล์
    • ย้อนกลับการเปลี่ยนแปลง (ไฟล์ยังคงแสดงตามที่เปลี่ยนแปลง)
    • กระทำมัน
  • ใช้ขั้นต่ำเปล่าเท่านั้น .gitattributes
  • สั่งให้ผู้ใช้ตั้งค่าที่core.autocrlfอธิบายไว้ข้างต้นเป็นค่าเริ่มต้น
  • ไม่นับ 100% .gitattributesในการปรากฏตัวของ git-clients ของ IDEs อาจเพิกเฉยหรือทำให้แตกต่างกัน

ตามที่กล่าวมาบางสิ่งสามารถเพิ่มในคุณลักษณะ git:

# Always checkout with LF
*.sh            text eol=lf
# Always checkout with CRLF
*.bat           text eol=crlf

ฉันคิดว่าตัวเลือกที่ปลอดภัยอื่น ๆ.gitattributesแทนการใช้การตรวจจับอัตโนมัติสำหรับไฟล์ไบนารี:

  • -text(เช่นสำหรับ*.zipหรือ*.jpgไฟล์: จะไม่ถือว่าเป็นข้อความดังนั้นจะไม่มีการพยายามแปลงที่ลงท้ายด้วยบรรทัด Diff อาจเป็นไปได้ผ่านโปรแกรมแปลง)
  • text !eol(เช่น*.java, *.html:.. ถือว่าเป็นข้อความ แต่การตั้งค่ารูปแบบ EOL ไม่ได้ตั้งค่าการตั้งค่าดังนั้นลูกค้าจะใช้)
  • -text -diff -merge(เช่นสำหรับ*.hugefile: ไม่ถือว่าเป็นข้อความไม่สามารถเป็นไปได้ / รวมกัน)

--- อัพเดตก่อนหน้า ---

ตัวอย่างหนึ่งที่เจ็บปวดของลูกค้าที่จะส่งไฟล์ผิด:

NetBeans 8.2 (หน้าต่าง) ผิดจะกระทำไฟล์ข้อความทั้งหมดที่มีCRLFs เว้นแต่คุณได้อย่างชัดเจนตั้งเป็นระดับโลกcore.autocrlf สิ่งนี้ขัดแย้งกับพฤติกรรมไคลเอ็นต์ git มาตรฐานและทำให้เกิดปัญหามากมายในภายหลังในขณะที่อัพเดต / รวม นี่คือสิ่งที่ทำให้บาง ไฟล์ปรากฏที่แตกต่างกัน (แม้ว่าพวกเขาไม่ได้) แม้เมื่อคุณย้อนกลับ
พฤติกรรมเดียวกันใน netbeans เกิดขึ้นแม้ว่าคุณได้เพิ่มความถูกต้อง.gitattributesให้กับโครงการของคุณ

การใช้คำสั่งต่อไปนี้หลังจากการคอมมิท, อย่างน้อยจะช่วยให้คุณตรวจพบตั้งแต่เนิ่น ๆ ว่า git repo ของคุณมีปัญหาการสิ้นสุดบรรทัด: git grep -I --files-with-matches --perl-regexp '\r' HEAD

ฉันใช้เวลาหลายชั่วโมงเพื่อหาวิธีที่ดีที่สุดเท่าที่จะเป็นไปได้.gitattributesในที่สุดเพื่อตระหนักว่าฉันไม่สามารถเชื่อใจได้
น่าเสียดายที่ตราบใดที่มีเอดิเตอร์ที่ใช้ JGit อยู่ (ซึ่งไม่สามารถจัดการ.gitattributesได้อย่างถูกต้อง) โซลูชันที่ปลอดภัยคือบังคับให้ LF ทุกที่แม้แต่ในระดับเอดิเตอร์

ใช้anti-CRLFน้ำยาฆ่าเชื้อต่อไปนี้


ฉันเห็นด้วยกับคุณว่านี่เป็นวิธีที่ดีที่สุดไม่มีใครควรใช้โปรแกรมแก้ไขที่ไม่มีการสนับสนุน LF แต่ระวังด้วย.gitattributesบรรทัดของคุณมันมีผลลัพธ์ที่ไม่ตั้งใจใน Git <2.10, ดูstackoverflow.com/a/29508751/2261442
phk

ยี้ ... ฉันมีคำตอบมากมายสำหรับการสนับสนุนของฉันgit config --global core.autocrlf falseและแนะนำให้จัดการกับ eol ใน.gitattributesคำสั่งเท่านั้น
VonC

5

นี่เป็นเพียงวิธีแก้ปัญหา:

ในกรณีปกติให้ใช้วิธีแก้ปัญหาที่มาพร้อมกับ git ใช้งานได้ดีในกรณีส่วนใหญ่ บังคับให้เป็น LF หากคุณแบ่งปันการพัฒนาบนระบบที่ใช้ Windows และ Unix ด้วยการตั้งค่า. gitattributes

ในกรณีของฉันมีโปรแกรมเมอร์มากกว่า 10 คนกำลังพัฒนาโครงการใน Windows โปรเจ็กต์นี้ถูกเช็กอินด้วย CRLF และไม่มีตัวเลือกในการบังคับให้ LF

การตั้งค่าบางอย่างถูกเขียนขึ้นภายในเครื่องของฉันโดยไม่มีผลกับรูปแบบ LF ดังนั้นไฟล์บางไฟล์จึงถูกเปลี่ยนเป็น LF ทั่วโลกในการเปลี่ยนแปลงไฟล์ขนาดเล็กแต่ละไฟล์

ทางออกของฉัน:

Windows-Machines: ให้ทุกอย่างเหมือนเดิม ไม่ต้องสนใจอะไรเลยเนื่องจากคุณเป็นนักพัฒนา 'หมาป่าโลน' ที่เป็นหน้าต่างเริ่มต้นและคุณต้องจัดการดังนี้: "ไม่มีระบบอื่นในโลกกว้างใช่ไหม"

Unix-เครื่อง

  1. เพิ่มบรรทัดต่อไปนี้ใน[alias]ส่วนของการกำหนดค่า คำสั่งนี้แสดงรายการไฟล์ที่ถูกเปลี่ยนแปลง (เช่นที่ถูกแก้ไข / ใหม่):

    lc = "!f() { git status --porcelain \
                 | egrep -r \"^(\?| ).\*\\(.[a-zA-Z])*\" \
                 | cut -c 4- ; }; f "
  2. แปลงไฟล์ที่เปลี่ยนแปลงทั้งหมดเหล่านั้นเป็นรูปแบบ dos:

    unix2dos $(git lc)
  3. ทางเลือก ...

    1. สร้าง git hookสำหรับการกระทำนี้เพื่อทำให้กระบวนการนี้เป็นแบบอัตโนมัติ

    2. ใช้พารามิเตอร์และรวมมันและแก้ไขgrepฟังก์ชั่นเพื่อให้ตรงกับชื่อไฟล์เฉพาะเช่น:

      ... | egrep -r "^(\?| ).*\.(txt|conf)" | ...
    3. รู้สึกสะดวกสบายยิ่งขึ้นด้วยการใช้ทางลัดเพิ่มเติม:

      c2dos = "!f() { unix2dos $(git lc) ; }; f "

      ... และไล่สิ่งที่แปลงแล้วด้วยการพิมพ์

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