Buộc LF eol trong git repo và bản sao làm việc


170

Tôi có một kho git được lưu trữ trên github. Nhiều tệp ban đầu được phát triển trên Windows và tôi không quá cẩn thận về kết thúc dòng. Khi tôi thực hiện cam kết ban đầu, tôi cũng không có cấu hình git nào để thực thi các kết thúc dòng chính xác. Kết quả cuối cùng là tôi có một số tệp có kết thúc dòng CRLF trong kho github của mình.

Tôi hiện đang phát triển một phần trên Linux và tôi muốn dọn sạch các kết thúc dòng. Làm cách nào tôi có thể đảm bảo các tệp được lưu trữ chính xác với LF trên github và có LF trong bản sao làm việc của tôi?

Tôi đã thiết lập một .gitattributestập tin có chứa text eol=LF; đúng không? Với cam kết và thúc đẩy đó, tôi có thể chỉ cần rmrepo cục bộ của mình và sao chép lại từ github để có được hiệu quả mong muốn không?


1
bản sao có thể của git thay thế LF bằng CRLF
Lazy Badger


Không ai trong số đó là những gì tôi đang hỏi. Tôi là nhà phát triển duy nhất và tôi khá sẵn lòng thiết lập tất cả các máy của mình như nhau. Tôi có một repo hiện có với một số tệp CRLF đã được cam kết với nó và một vài bản sao trên các máy khác nhau. Làm cách nào tôi có thể cập nhật repo và mỗi bản sao hoạt động, để có LF ở khắp mọi nơi?
Chowlett

Bạn đã xem hướng dẫn Github này ?
Andy

Câu trả lời:


237

Không có một chút thông tin về tập tin nào trong kho lưu trữ của bạn (mã nguồn thuần, hình ảnh, tệp thực thi, ...), thật khó để trả lời câu hỏi :)

Bên cạnh đó, tôi sẽ xem xét rằng bạn sẵn sàng mặc định cho LF là kết thúc dòng trong thư mục làm việc của bạn bởi vì bạn sẵn sàng đảm bảo rằng các tệp văn bản có kết thúc dòng LF trong kho lưu trữ .git của bạn khi bạn làm việc trên Windows hoặc Linux . Quả thực an toàn hơn xin lỗi ....

Tuy nhiên, có một giải pháp thay thế tốt hơn: Lợi ích từ các kết thúc dòng LF trong máy tính Linux của bạn, các kết thúc dòng CRLF trong các kết thúc dòng máy tính và dòng máy tính Windows của Windows trong kho lưu trữ của bạn.

Vì bạn đang làm việc một phần trên Linux và Windows, hãy đảm bảo core.eolđược đặt thành nativecore.autocrlfđược đặt thành true.

Sau đó, thay thế nội dung của .gitattributestệp của bạn bằng cách sau

* text=auto

Điều này sẽ cho phép Git xử lý chuyển đổi kết thúc dòng tự động cho bạn, trên các cam kết và kiểm tra. Các tệp nhị phân sẽ không bị thay đổi, các tệp được phát hiện là tệp văn bản sẽ thấy các kết thúc dòng được chuyển đổi nhanh chóng.

Tuy nhiên, khi bạn biết nội dung của kho lưu trữ của mình, bạn có thể giúp Git và giúp anh ta phát hiện các tệp văn bản từ các tệp nhị phân.

Miễn là bạn làm việc trong dự án xử lý ảnh dựa trên C, thay thế nội dung .gitattributestệp của bạn bằng cách sau

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

Điều này sẽ đảm bảo các tệp mà phần mở rộng là c, h hoặc txt sẽ được lưu trữ với các kết thúc dòng LF trong repo của bạn và sẽ có các kết thúc dòng gốc trong thư mục làm việc. Các tập tin Jpeg sẽ không được chạm vào. Tất cả những cái khác sẽ được hưởng lợi từ cùng một bộ lọc tự động như đã thấy ở trên.

Để có được sự hiểu biết sâu sắc hơn về các chi tiết bên trong của tất cả những điều này, tôi khuyên bạn nên đi sâu vào bài viết rất hay này "Hãy nhớ đến cuối dòng của bạn" từ Tim Clem, một Githubber.

Là một ví dụ trong thế giới thực, bạn cũng có thể xem qua cam kết này , nơi những thay đổi đó đối với một .gitattributestệp được thể hiện.

CẬP NHẬT câu trả lời xem xét nhận xét sau

Tôi thực sự không muốn CRLF trong các thư mục Windows của mình, vì môi trường Linux của tôi thực sự là một VirtualBox chia sẻ thư mục Windows

Có ý nghĩa. Cảm ơn bạn đã làm rõ. Trong bối cảnh cụ thể này, .gitattributestập tin tự nó sẽ không đủ.

Chạy các lệnh sau đối với kho lưu trữ của bạn

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

Vì kho lưu trữ của bạn được chia sẻ giữa môi trường Linux và Windows của bạn, điều này sẽ cập nhật tệp cấu hình cục bộ cho cả hai môi trường. core.eolsẽ đảm bảo các tệp văn bản có kết thúc dòng LF khi thanh toán. core.autocrlfsẽ đảm bảo CRLF tiềm năng trong các tệp văn bản (ví dụ: hoạt động sao chép / dán) sẽ được chuyển đổi thành LF trong kho lưu trữ của bạn.

Theo tùy chọn, bạn có thể giúp Git phân biệt tệp văn bản gì bằng cách tạo .gitattributestệp chứa nội dung tương tự như sau:

# 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

Nếu bạn quyết định tạo một .gitattributestập tin, hãy cam kết nó .

Cuối cùng, đảm bảo git statusđề cập "không có gì để cam kết (làm sạch thư mục làm việc)" , sau đó thực hiện các thao tác sau

$ git checkout-index --force --all

Điều này sẽ tạo lại các tệp của bạn trong thư mục làm việc của bạn, có tính đến các thay đổi cấu hình và .gitattributestệp của bạn và thay thế bất kỳ CRLF tiềm năng nào bị bỏ qua trong các tệp văn bản của bạn.

Một khi điều này được thực hiện, mọi tệp văn bản trong thư mục làm việc của bạn S bear chịu các kết thúc dòng LF và git statusvẫn nên coi workdir là sạch.


34
Tôi thực sự không muốn CRLF trong các thư mục Windows của mình, vì môi trường Linux của tôi thực sự là một VirtualBox chia sẻ thư mục Windows; và trong khi Notepad ++, vv có thể xử lý chỉ có trên Windows, vithì CRLF không hài lòng lắm. Tôi chỉ muốn thay đổi nó core.autocrlffalse(hoặc input)?
Chowlett

5
Câu trả lời tuyệt vời. Lưu ý nhanh cho bất kỳ ai khác sử dụng thiết lập này: Dòng "* text = auto" phải là dòng đầu tiên trong tệp .gitattribution của bạn để các dòng tiếp theo có thể ghi đè cài đặt đó.
Ari Patrick

9
@CMCDragonkai Tùy thuộc vào vỏ của bạn, git checkout-index --force --allcó thể hoạt động tốt hơn. Điểm thứ hai có vẻ hơi lạc đề về câu hỏi ban đầu. Làm thế nào về việc hỏi một câu hỏi dành riêng?
nulltoken

8
Tôi không hiểu tại sao .gitattribut không thể xử lý trường hợp chia sẻ bản sao hoạt động giữa Linux và Windows. Chúng tôi không thể thiết lập texteol=lfđể đạt được kết quả tương tự như được mô tả trong câu trả lời của bạn thông qua core.eolcore.autocrlf?
DanielSank

10
git checkout-index --force --allkhông làm gì cho tôi Những gì hoạt động là danh sách các lệnh trong hướng dẫn GitHub để xử lý vấn đề này.
Roman Starkov

126

Bắt đầu với git 2.10 (phát hành 2016-09-03), không cần thiết phải liệt kê riêng từng tệp văn bản. Git 2.10 đã sửa lỗi hành vi của text = auto cùng với eol = lf . Nguồn .

.gitattributes tập tin trong thư mục gốc của kho git của bạn:

* text=auto eol=lf

Thêm và cam kết nó.

Sau đó, bạn có thể thực hiện theo các bước và tất cả các tệp được chuẩn hóa ngay bây giờ:

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.

Nguồn: Trả lời bằng kenorb .


7
Git 2.10 đã được phát hành vào ngày 03 tháng 9 năm 2016.
stil

Tôi đã chạy cái này và nó gạch tất cả các tập tin phi văn bản của tôi
Anthony

Bạn rõ ràng có thể đặt chế độ nhị phân cho các tệp nhất định. - Tôi tự hỏi tại sao phát hiện tự động (vẫn?!)
Bị

Đây phải là câu trả lời được chấp nhận.
CletusW

25

Để buộc các kết thúc dòng LF cho tất cả các tệp văn bản, bạn có thể tạo .gitattributestệp ở cấp cao nhất của kho lưu trữ của mình bằng các dòng sau (thay đổi theo ý muốn):

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

đảm bảo rằng tất cả các tệp mà Git coi là tệp văn bản có các LFkết thúc dòng được chuẩn hóa ( ) trong kho lưu trữ (thông thường core.eolcấu hình sẽ kiểm soát cái nào bạn có theo mặc định).

Dựa trên các cài đặt thuộc tính mới, mọi tệp văn bản chứa CRLF sẽ được Git chuẩn hóa. Nếu điều này không tự động xảy ra, bạn có thể làm mới kho lưu trữ theo cách thủ công sau khi thay đổi kết thúc dòng, do đó bạn có thể quét lại và cam kết thư mục làm việc theo các bước sau (được cung cấp thư mục làm việc sạch):

$ 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"

hoặc theo tài liệu 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.

Xem thêm: @Charles Bailey bài .

Ngoài ra, nếu bạn muốn loại trừ bất kỳ tệp nào không được coi là văn bản, hãy bỏ đặt thuộc tính văn bản của chúng, ví dụ:

manual.pdf      -text

Hoặc đánh dấu nó rõ ràng là nhị phân:

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

Để xem một số tệp chuẩn hóa git nâng cao hơn, hãy kiểm tra .gitattributestại lõi Drupal :

# 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

Xem thêm:


2
1. text=autolà sai lệch. Bạn không thể sử dụng text=autoeolcùng nhau. Cài đặt eolvô hiệu hóa tự động phát hiện các tập tin văn bản. Đây là lý do tại sao bạn phải chỉ định tất cả các loại tệp. Nếu autođược kích hoạt, bạn sẽ không cần tất cả điều đó. 2. Bạn không cần texteol=lf. eol=lfhiệu quả thiết lập text.
Ben

2
Thứ 2 @Ben đã nói, cấu hình này hiện đang sai và nguy hiểm nếu bạn không đánh dấu rõ ràng tất cả các tệp nhị phân.
Michael R

1
Tôi đã đọc rằng * text=auto eol=lfđầu tiên text=autobị ghi đè bởi eol=lf. Bạn đã tìm thấy tính năng này ở đâu? Đây là nguồn của tôi: stackoverflow.com/questions/29435156/ Cách
CMCDragonkai

Xóa * text=auto eol=lfkhỏi ví dụ, vì nó cũng bị xóa khỏi Drupal. Xem xét loại bỏ ý kiến ​​là tốt.
kenorb

4
Điều quan trọng cần lưu ý là những gì @Ben nói không còn đúng nữa và đó luôn là một lỗi - không phải là hành vi có chủ đích.
Semmel
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.