บังคับให้ LF eol ใน repo คอมไพล์และสำเนาการทำงาน


170

ฉันมีที่เก็บ git บน github ไฟล์จำนวนมากได้รับการพัฒนาในตอนแรกบน Windows และฉันก็ไม่ระมัดระวังเกี่ยวกับการสิ้นสุดบรรทัด เมื่อฉันทำการคอมมิชชันเริ่มต้นฉันยังไม่มีการกำหนดค่า git ใด ๆ เพื่อบังคับใช้การสิ้นสุดบรรทัดที่ถูกต้อง ผลที่สุดคือฉันมีไฟล์จำนวนมากที่มีปลายสาย CRLF ในที่เก็บ github ของฉัน

ตอนนี้ฉันกำลังพัฒนาบางส่วนบน Linux และฉันต้องการล้างข้อมูลท้ายบรรทัด ฉันจะมั่นใจได้อย่างไรว่าไฟล์จะถูกจัดเก็บอย่างถูกต้องด้วย LF บน github และมี LF ในสำเนาการทำงานของฉัน

ฉันได้ตั้งค่า.gitattributesไฟล์ที่มีtext eol=LF; ถูกต้องหรือไม่ ด้วยความมุ่งมั่นและผลักดันที่ฉันสามารถเพียงrmrepo ท้องถิ่นของฉันและโคลนอีกครั้งจาก GitHub เพื่อให้ได้ผลที่ต้องการ?


1
สำเนาซ้ำที่เป็นไปได้ของgit แทนที่ LF ด้วย CRLF
Lazy Badger


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

คุณดูคู่มือ Github นี้หรือไม่?
Andy

คำตอบ:


237

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

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

อย่างไรก็ตามมีทางเลือกอื่นที่ดีกว่า: ได้รับประโยชน์จากการสิ้นสุดของบรรทัด LF ในเวิร์กบุ๊ก Linux ของคุณ, การสิ้นสุดบรรทัด CRLF ใน Windows workdir และการสิ้นสุดบรรทัด LF ในพื้นที่เก็บข้อมูลของคุณ

ในขณะที่คุณกำลังบางส่วนทำงานบน Linux และ Windows ให้แน่ใจว่าcore.eolมีการตั้งค่าnativeและมีการตั้งค่าcore.autocrlftrue

จากนั้นแทนที่เนื้อหาของ.gitattributesไฟล์ของคุณด้วยสิ่งต่อไปนี้

* text=auto

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

อย่างไรก็ตามเมื่อคุณทราบเนื้อหาของที่เก็บของคุณคุณอาจมอบ Git และช่วยให้เขาตรวจจับไฟล์ข้อความจากไฟล์ไบนารี

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

* text=auto
*.txt text
*.c text
*.h text
*.jpg binary

สิ่งนี้จะทำให้แน่ใจได้ว่าไฟล์ใดที่นามสกุลเป็น c, h หรือ txt จะถูกเก็บไว้ที่ปลายสาย LF ใน repo ของคุณและจะมีจุดสิ้นสุดดั้งเดิมในไดเรกทอรีการทำงาน ไฟล์ Jpeg จะไม่ถูกแตะต้อง อื่น ๆ ทั้งหมดจะได้รับประโยชน์จากตัวกรองอัตโนมัติแบบเดียวกับที่เห็นด้านบน

เพื่อให้ได้รับความเข้าใจที่ลึกซึ้งยิ่งขึ้นเกี่ยวกับรายละเอียดภายในของทั้งหมดนี้ฉันขอแนะนำให้คุณดำดิ่งลงในโพสต์ที่ดีมากนี้"Mind the End of the Line" ของคุณจาก Tim Clem, Githubber

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

อัปเดตเป็นคำตอบโดยพิจารณาจากความคิดเห็นต่อไปนี้

ที่จริงฉันไม่ต้องการ CRLF ในไดเรกทอรี Windows ของฉันเพราะสภาพแวดล้อม Linux ของฉันคือ VirtualBox ที่ใช้ร่วมกันในไดเรกทอรี Windows

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

รันคำสั่งต่อไปนี้กับที่เก็บของคุณ

$ git config core.eol lf
$ git config core.autocrlf input

เนื่องจากที่เก็บของคุณแชร์ระหว่างสภาพแวดล้อม Linux และ Windows ของคุณสิ่งนี้จะอัปเดตไฟล์กำหนดค่าท้องถิ่นสำหรับทั้งสองสภาพแวดล้อม core.eolจะตรวจสอบให้แน่ใจว่าไฟล์ข้อความมีจุดสิ้นสุดบรรทัด LF ในการชำระเงิน core.autocrlfจะช่วยให้มั่นใจศักยภาพ CRLF ในไฟล์ข้อความ (ที่เกิดจากการคัดลอก / วางการดำเนินงานเป็นต้น) จะถูกแปลงเป็น LF ในพื้นที่เก็บข้อมูลของคุณ

คุณสามารถช่วย Git แยกแยะว่าอะไรคือไฟล์ข้อความโดยการสร้าง.gitattributesไฟล์ที่มีบางอย่างที่คล้ายกับต่อไปนี้:

# Autodetect text files
* text=auto

# ...Unless the name matches the following
# overriding patterns

# Definitively text files 
*.txt text
*.c text
*.h text

# Ensure those won't be messed up with
*.jpg binary
*.data binary

ถ้าคุณตัดสินใจที่จะสร้าง.gitattributesไฟล์กระทำมัน

สุดท้ายตรวจสอบให้แน่ใจว่าได้git statusกล่าวถึง"ไม่มีสิ่งใดที่จะกระทำ (ทำความสะอาดไดเรกทอรีทำงาน)"จากนั้นดำเนินการต่อไปนี้

$ git checkout-index --force --all

สิ่งนี้จะสร้างไฟล์ของคุณใหม่ในไดเรกทอรีทำงานโดยคำนึงถึงการเปลี่ยนแปลงการกำหนดค่าของคุณและ.gitattributesไฟล์และแทนที่ CRLF ที่อาจถูกมองข้ามในไฟล์ข้อความของคุณ

เมื่อทำสิ่งนี้เสร็จแล้วไฟล์ข้อความทุกไฟล์ในไดเรกทอรีการทำงานของคุณจะมีจุดสิ้นสุดบรรทัด LF และgit statusควรถือว่าเวิร์กดีร์นั้นสะอาด


34
จริง ๆ แล้วฉันไม่ต้องการ CRLF ในไดเรกทอรี Windows ของฉันเพราะสภาพแวดล้อม Linux ของฉันคือ VirtualBox ที่ใช้ร่วมกันในไดเรกทอรี Windows; และในขณะที่ Notepad ++ เป็นต้นสามารถจัดการกับ LF-only บน Windows ได้ แต่viCRLF ก็มีความสุขน้อยลง ฉันแค่ต้องการเปลี่ยนมันเพื่อให้core.autocrlfเป็นfalse(หรือinput)?
Chowlett

5
คำตอบที่ยอดเยี่ยม บันทึกย่อแบบด่วนสำหรับผู้อื่นที่ใช้การตั้งค่านี้: บรรทัด "* text = auto" ควรเป็นบรรทัดแรกในไฟล์. gitattributes ของคุณเพื่อให้บรรทัดถัดไปสามารถแทนที่การตั้งค่านั้นได้
Ari Patrick

9
@CMCDragonkai git checkout-index --force --allอาจทำงานได้ดีขึ้น จุดที่สองจะมีลักษณะคล้ายกับคำถามต้นฉบับ ถ้าถามคำถามเฉพาะ
nulltoken

8
ฉันไม่เข้าใจว่าทำไม. gitattributes ไม่สามารถจัดการกับกรณีของการแบ่งปันสำเนาการทำงานระหว่าง Linux และ Windows เราไม่สามารถตั้งค่าtextและeol=lfเพื่อให้ได้ผลลัพธ์เดียวกันกับที่อธิบายไว้ในคำตอบของคุณผ่านทางcore.eolและcore.autocrlf?
DanielSank

10
git checkout-index --force --allไม่ทำอะไรเลยสำหรับฉัน การทำงานคือรายการคำสั่งในคำแนะนำ GitHubสำหรับจัดการกับปัญหานี้
Roman Starkov

126

เริ่มต้นด้วย git 2.10 (เผยแพร่เมื่อ 2016-09-03) ไม่จำเป็นต้องระบุแต่ละไฟล์ข้อความแยกกัน Git 2.10 การแก้ไขพฤติกรรมของข้อความ = อัตโนมัติร่วมกับ EOL แหล่ง

.gitattributes ไฟล์ในรูทของที่เก็บ git ของคุณ:

* text=auto eol=lf

เพิ่มและกระทำมัน

หลังจากนั้นคุณสามารถทำตามขั้นตอนและไฟล์ทั้งหมดจะถูกทำให้เป็นมาตรฐานในขณะนี้:

git rm --cached -r .  # Remove every file from git's index.
git reset --hard      # Rewrite git's index to pick up all the new line endings.

ที่มา: คำตอบโดย kenorb


7
Git 2.10 ได้รับการปล่อยตัวในวันที่ 3 กันยายน 2559
สไตล์

ฉันรันสิ่งนี้และมันก็ก่ออิฐไฟล์ที่ไม่ใช่ข้อความทั้งหมดของฉัน
แอนโธนี

คุณสามารถตั้งค่าโหมดไบนารีอย่างชัดเจนเป็นไฟล์บางไฟล์ได้ - ฉันสงสัยว่าทำไมการตรวจจับอัตโนมัติถึง (ยัง?!) หักบางไฟล์
koppor

นี่ควรเป็นคำตอบที่ยอมรับได้
CletusW

25

ในการบังคับให้จบบรรทัด LF สำหรับไฟล์ข้อความทั้งหมดคุณสามารถสร้าง.gitattributesไฟล์ในระดับบนสุดของที่เก็บของคุณด้วยบรรทัดต่อไปนี้ (เปลี่ยนตามที่ต้องการ):

# Ensure all C and PHP files use LF.
*.c         eol=lf
*.php       eol=lf

ซึ่งทำให้มั่นใจได้ว่าไฟล์ทั้งหมดที่ Git พิจารณาว่าเป็นไฟล์ข้อความมีLFบรรทัดที่ลงท้ายด้วยบรรทัดมาตรฐาน ( ) ในพื้นที่เก็บข้อมูล (โดยปกติจะเป็นcore.eolตัวควบคุมการกำหนดค่าที่คุณต้องมีตามค่าเริ่มต้น)

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

$ echo "* text=auto" >> .gitattributes
$ rm .git/index     # Remove the index to force Git to
$ git reset         # re-scan the working directory
$ git status        # Show files that will be normalized
$ git add -u
$ git add .gitattributes
$ git commit -m "Introduce end-of-line normalization"

หรือตามเอกสาร GitHub :

git add . -u
git commit -m "Saving files before refreshing line endings"
git rm --cached -r . # Remove every file from Git's index.
git reset --hard # Rewrite the Git index to pick up all the new line endings.
git add . # Add all your changed files back, and prepare them for a commit.
git commit -m "Normalize all the line endings" # Commit the changes to your repository.

ดูเพิ่มเติม: โพสต์ @Charles เบลีย์

นอกจากนี้หากคุณต้องการยกเว้นไฟล์ใด ๆ ที่ไม่ถูกถือว่าเป็นข้อความให้ยกเลิกการตั้งค่าแอททริบิวข้อความของพวกเขาเช่น

manual.pdf      -text

หรือทำเครื่องหมายว่าเป็นไบนารีอย่างชัดเจน:

# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary

หากต้องการดูไฟล์การปรับมาตรฐาน git ขั้นสูงเพิ่มเติมให้ตรวจสอบ.gitattributesที่Drupal core :

# Drupal git normalization
# @see https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
# @see https://www.drupal.org/node/1542048

# Normally these settings would be done with macro attributes for improved
# readability and easier maintenance. However macros can only be defined at the
# repository root directory. Drupal avoids making any assumptions about where it
# is installed.

# Define text file attributes.
# - Treat them as text.
# - Ensure no CRLF line-endings, neither on checkout nor on checkin.
# - Detect whitespace errors.
#   - Exposed by default in `git diff --color` on the CLI.
#   - Validate with `git diff --check`.
#   - Deny applying with `git apply --whitespace=error-all`.
#   - Fix automatically with `git apply --whitespace=fix`.

*.config  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.css     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.dist    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.engine  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.html    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=html
*.inc     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.install text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.js      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.json    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.lock    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.map     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.md      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.module  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.php     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.po      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.profile text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.script  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.sh      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.sql     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.svg     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.theme   text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.twig    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.txt     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.xml     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.yml     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2

# Define binary file attributes.
# - Do not treat them as text.
# - Include binary diff in patches instead of "binary files differ."
*.eot     -text diff
*.exe     -text diff
*.gif     -text diff
*.gz      -text diff
*.ico     -text diff
*.jpeg    -text diff
*.jpg     -text diff
*.otf     -text diff
*.phar    -text diff
*.png     -text diff
*.svgz    -text diff
*.ttf     -text diff
*.woff    -text diff
*.woff2   -text diff

ดูสิ่งนี้ด้วย:


2
1. text=autoกำลังทำให้เข้าใจผิด คุณไม่สามารถใช้text=autoและeolร่วมกัน การตั้งค่าeolปิดใช้งานการตรวจจับไฟล์ข้อความโดยอัตโนมัติ นี่คือเหตุผลที่คุณต้องระบุไฟล์ประเภทเหล่านั้นทั้งหมด หากautoเปิดใช้งานคุณจะไม่จำเป็นต้องใช้ทั้งหมด 2. คุณไม่จำเป็นและtext ได้อย่างมีประสิทธิภาพชุด eol=lfeol=lftext
Ben

2
สิ่งที่ @Ben กล่าวไว้ตอนนี้การกำหนดค่านี้ผิดและอันตรายหากคุณไม่ทำเครื่องหมายไบนารีทั้งหมดอย่างชัดเจน
Michael R

1
ผมเคยอ่านว่า* text=auto eol=lfคนแรกที่จะถูกแทนที่โดยtext=auto eol=lfคุณพบคุณลักษณะนี้ที่ไหน นี่คือที่มาของฉัน: stackoverflow.com/questions/29435156/…
CMCDragonkai

นำออก* text=auto eol=lfจากตัวอย่างเนื่องจากถูกลบออกจาก Drupal เช่นกัน พิจารณาลบความคิดเห็นด้วย
kenorb

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