What's the strategy for handling CRLF (carriage return, line feed) with Git?

I tried committing files with CRLF-ending lines, but it failed.

I spent a whole work day on my Windows computer trying different strategies and was almost drawn to stop trying to use Git and instead try Mercurial.

How to properly handle CRLF line endings?


Solution 1:

Almost four years after asking this question, I have finally found an answer that completely satisfies me!

See the details in github:help's guide to Dealing with line endings.

Git allows you to set the line ending properties for a repo directly using the text attribute in the .gitattributes file. This file is committed into the repo and overrides the core.autocrlf setting, allowing you to ensure consistent behaviour for all users regardless of their git settings.

And thus

The advantage of this is that your end of line configuration now travels with your repository and you don't need to worry about whether or not collaborators have the proper global settings.

Here's an example of a .gitattributes file

# 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

There is a convenient collection of ready to use .gitattributes files for the most popular programming languages. It's useful to get you started.

Once you've created or adjusted your .gitattributes, you should perform a once-and-for-all line endings re-normalization.

Note that the GitHub Desktop app can suggest and create a .gitattributes file after you open your project's Git repo in the app. To try that, click the gear icon (in the upper right corner) > Repository settings ... > Line endings and attributes. You will be asked to add the recommended .gitattributes and if you agree, the app will also perform a normalization of all the files in your repository.

Finally, the Mind the End of Your Line article provides more background and explains how Git has evolved on the matters at hand. I consider this required reading.

You've probably got users in your team who use EGit or JGit (tools like Eclipse and TeamCity use them) to commit their changes. Then you're out of luck, as @gatinueta explained in this answer's comments:

This setting will not satisfy you completely if you have people working with Egit or JGit in your team, since those tools will just ignore .gitattributes and happily check in CRLF files https://bugs.eclipse.org/bugs/show_bug.cgi?id=342372

One trick might be to have them commit their changes in another client, say SourceTree. Our team back then preferred that tool to Eclipse's EGit for many use cases.

Who said software is easy? :-/

Solution 2:

Don't convert line endings. It's not the VCS's job to interpret data -- just store and version it. Every modern text editor can read both kinds of line endings anyway.

Solution 3:

You almost always want autocrlf=input unless you really know what you are doing.

Some additional context below:

It should be either core.autocrlf=true if you like DOS ending or core.autocrlf=input if you prefer unix-newlines. In both cases, your Git repository will have only LF, which is the Right Thing. The only argument for core.autocrlf=false was that automatic heuristic may incorrectly detect some binary as text and then your tile will be corrupted. So, core.safecrlf option was introduced to warn a user if a irreversable change happens. In fact, there are two possibilities of irreversable changes -- mixed line-ending in text file, in this normalization is desirable, so this warning can be ignored, or (very unlikely) that Git incorrectly detected your binary file as text. Then you need to use attributes to tell Git that this file is binary.

The above paragraph was originally pulled from a thread on gmane.org, but it has since gone down.

Solution 4:

Two alternative strategies to get consistent about line-endings in mixed environments (Microsoft + Linux + Mac):

A. Global All Repositories Setup

  1. Convert all to one format

    find . -type f -not -path "./.git/*" -exec dos2unix {} \;
    git commit -a -m 'dos2unix conversion'
    
  2. Set core.autocrlf to input on Linux/UNIX or true on MS Windows (repository or global)

    git config --global core.autocrlf input
    
  3. Optionally, set core.safecrlf to true (to stop) or warn (to sing:) to add extra guard comparing if the reversed newline transformation would result in the same file

    git config --global core.safecrlf true
    

B. Or per Repository Setup

  1. Convert all to one format

    find . -type f -not -path "./.git/*" -exec dos2unix {} \;
    git commit -a -m 'dos2unix conversion'
    
  2. Add a .gitattributes file to your repository

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

Don't worry about your binary files—Git should be smart enough about them.


More about safecrlf/autocrlf variables