Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git core.safecrlf different behavior on files with same line endings

I have Windows machine with VS project and I use both Visual Studio and tools from Cygwin environment including Git. Sometimes I get different line endings in files after editing. I want simple solution to check files' line ending consistency before they go to the repo. Git's core.safecrlf is the right thing I suppose. Now I have a strange behavior:

Files A and B with following parameters:

$file A
A: HTML document, UTF-8 Unicode text, with CRLF line terminators
$file B
B: HTML document, UTF-8 Unicode (with BOM) text, with CRLF line terminators

File A is already in repo, file B is new one. Note, both have CRLF line endings. Now try to stage them, core.safecrlf is true.

$git add A  # ok
$git add B  # fails
fatal: CRLF would be replaced by LF in B.

Am using core.safecrlf correctly? Or maybe I need to write hook to check files?

Notes:

  • tried with different file encodings (with and without BOM), no difference.
  • there's related core.autocrlf feature in Git, added it to tags (Stackoverflow has no tag for core.safecrlf)
  • git version 1.8.5.rc1.17.g0ecd94d (compiled from sources under Cygwin)

EDIT #1: checked out core.autocrlf - it was input. Changed to false, now I can add both files. Why?

like image 810
Rast Avatar asked Nov 14 '13 12:11

Rast


People also ask

Does git change line endings?

Git has changed line endings to match your new configuration. To ensure that all the line endings in your repository match your new configuration, backup your files with Git, delete all files in your repository (except the . git directory), then restore the files all at once.

Should I use CRLF or LF?

Whereas Windows follows the original convention of a carriage return plus a line feed ( CRLF ) for line endings, operating systems like Linux and Mac use only the line feed ( LF ) character. The history of these two control characters dates back to the era of the typewriter.

Why does LF replace CRLF?

The default behavior for git on windows is to convert LF to CRLF, because some editors in Windows don't know how to handle LF (e.g. Notepad would ignore them and display everything as one line of text). The choice of line ending is a project preference.

What is CRLF in git?

In Unix systems the end of a line is represented with a line feed (LF). In windows a line is represented with a carriage return (CR) and a line feed (LF) thus (CRLF). when you get code from git that was uploaded from a unix system they will only have an LF.


2 Answers

According to your later edit core.autocrlf = input was the original setting. With this setting CRLF is converted to LF when checked in to the repository and is kept that way when checked out. This means a non Unix line endings aware editor like Notepad would mess up the appearance of a checked out version of the file. It would be one giant long line.

FWIW core.autocrlf = input is the preferred setting on Unix systems and using the default cygwin build probably set it that way. In Windows the recommended settings is core.autocrlf = true which is what msysgit recommends

core.safecrlf = true aborts the conversion of a file if checking out the file will result in a changed and possibly damaged file which would be the case if Notepad was the editor. This is why file B was aborted because it would be messed up in an editor like Notepad. The difference between core.SAFEcrlf and core.AUTOcrlf should be noted. It is one of the eyes glazing over issues in understanding git line endings

core.autocrlf = false is don't care mode. It will check in and check out the files exactly as they are, which is why the commits now work. This is not very smart and is not recommended because it causes problems if the files are edited on both Windows and Unix systems and also if another users core.autocrlf settings differ and change the file endings.

My own preference is to set core.autocrlf to input on Windows if all the Windows editors and other text file processing tools on the project are Unix line ending aware, otherwise set it to core.autocrlf = true for Windows and core.autocrlf = input for Unix. In any case this approach is outmoded by the superior method of the .gitattributes file.

The .gitattributes file method processes files based on the file name and is maintained in all users environments as it is checked out into the working directory like .gitignore. The settings for as many file names and types as are relevant to your project should be added to .gitattributes. Your configuration then falls back onto the local core.autocrlf and core.safecrlf settings if the file name is not matched in .gitattributes. Adding * text=auto at the top of .gitattributes will cause git to do a best guess on file names which are not matched by the later .gitattributes settings.

This web page, Mind the End of Your Line helped me understand the issue better. You might read for more background on the issue.

like image 170
vfclists Avatar answered Sep 23 '22 19:09

vfclists


The CR LF line ending choices are not that easy to understand. There are two places for the descriptions in that it is covered both in Git-attributes and Git-config manuals.

Initially there were the autocrlf settings, and then there were the newer versions which have some potential incompatibilities (i.e. do unexpected things as you indicate).

I tend to set the eol=LF, which makes all text files be committed as LF line endings (you can set attributes as to which files are considered text) and then add the safecrlf for doing a round trip check.

like image 37
Philip Oakley Avatar answered Sep 24 '22 19:09

Philip Oakley