I've read a lot of different questions and answers on Stack Overflow as well as git documentation on how the core.autocrlf setting works.
This is my understanding from what I've read:
Unix and Mac OSX (pre-OSX uses CR) clients use LF line endings.
Windows clients use CRLF line endings.
When core.autocrlf is set to true on the client, the git repository always stores files in LF line ending format and line endings in files on the client are converted back and forth on check out / commit for clients (i.e. Windows) that use non-LF line endings, no matter what format the line endings files are on the client (this disagrees with Tim Clem's definition - see update below).
Here is a matrix that tries to document the same for the 'input' and 'false' settings of core.autocrlf with question marks where I'm not sure of line ending conversion behavior.
My questions are:
- What should the question marks be?
- Is this matrix correct for the "non-question marks"?
I'll update the question marks from the answers as consensus appears to be formed.
core.autocrlf value true input false ---------------------------------------------------------- commit | convert ? ? new | to LF (convert to LF?) (no conversion?) commit | convert to ? no existing | LF (convert to LF?) conversion checkout | convert to ? no existing | CRLF (no conversion?) conversion
I'm not really looking for opinions on the pros and cons of the various settings. I'm just looking for data which makes it clear how to expect git to operate with each of the three settings.
--
Update 04/17/2012: After reading the article by Tim Clem linked by JJD in the comments, I have modified some of the values in the "unknown" values in the table above, as well as changing "checkout existing | true to convert to CRLF instead of convert to client". Here are the definitions he gives, which are more clear than anything I've seen elsewhere:
core.autocrlf = false
This is the default, but most people are encouraged to change this immediately. The result of using false is that Git doesn’t ever mess with line endings on your file. You can check in files with LF or CRLF or CR or some random mix of those three and Git does not care. This can make diffs harder to read and merges more difficult. Most people working in a Unix/Linux world use this value because they don’t have CRLF problems and they don’t need Git to be doing extra work whenever files are written to the object database or written out into the working directory.
core.autocrlf = true
This means that Git will process all text files and make sure that CRLF is replaced with LF when writing that file to the object database and turn all LF back into CRLF when writing out into the working directory. This is the recommended setting on Windows because it ensures that your repository can be used on other platforms while retaining CRLF in your working directory.
core.autocrlf = input
This means that Git will process all text files and make sure that CRLF is replaced with LF when writing that file to the object database. It will not, however, do the reverse. When you read files back out of the object database and write them into the working directory they will still have LFs to denote the end of line. This setting is generally used on Unix/Linux/OS X to prevent CRLFs from getting written into the repository. The idea being that if you pasted code from a web browser and accidentally got CRLFs into one of your files, Git would make sure they were replaced with LFs when you wrote to the object database.
Tim's article is excellent, the only thing I can think of that is missing is that he assumes the repository is in LF format, which is not necessarily true, especially for Windows only projects.
Comparing Tim's article to the highest voted answer to date by jmlane shows perfect agreement on the true and input settings and disagreement on the false setting.
The issue of EOLs in mixed-platform projects has been making my life miserable for a long time. The problems usually arise when there are already files with different and mixed EOLs already in the repo. This means that:
CRLF
andLF
in the same file.How this happens is not the issue here, but it does happen.
I ran some conversion tests on Windows for the various modes and their combinations.
Here is what I got, in a slightly modified table:
As you can see, there are 2 cases when conversion happens on commit (3 left columns). In the rest of the cases the files are committed as-is.
Upon checkout (3 right columns), there is only 1 case where conversion happens when:
core.autocrlf
istrue
andLF
EOL.Most surprising for me, and I suspect, the cause of many EOL problems is that there is no configuration in which mixed EOL like
CRLF
+LF
get normalized.Note also that "old" Mac EOLs of
CR
only also never get converted.This means that if a badly written EOL conversion script tries to convert a mixed ending file with
CRLF
s+LF
s, by just convertingLF
s toCRLF
s, then it will leave the file in a mixed mode with "lonely"CR
s wherever aCRLF
was converted toCRCRLF
.Git will then not convert anything, even in
true
mode, and EOL havoc continues. This actually happened to me and messed up my files really badly, since some editors and compilers (e.g. VS2010) don't like Mac EOLs.I guess the only way to really handle these problems is to occasionally normalize the whole repo by checking out all the files in
input
orfalse
mode, running a proper normalization and re-committing the changed files (if any). On Windows, presumably resume working withcore.autocrlf true
.The best explanation of how
core.autocrlf
works is found on the gitattributes man page, in thetext
attribute section.This is how
core.autocrlf
appears to work currently (or at least since v1.7.2 from what I am aware):core.autocrlf = true
LF
characters are normalized toCRLF
in your working tree; files that containCRLF
in the repository will not be touchedLF
characters in the repository, are normalized fromCRLF
toLF
when committed back to the repository. Files that containCRLF
in the repository will be committed untouched.core.autocrlf = input
CRLF
characters are normalized toLF
when committed back to the repository.core.autocrlf = false
core.eol
dictates EOL characters in the text files of your working tree.core.eol = native
by default, which means Windows EOLs areCRLF
and *nix EOLs areLF
in working trees.gitattributes
settings determines EOL character normalization for commits to the repository (default is normalization toLF
characters).I've only just recently researched this issue and I also find the situation to be very convoluted. The
core.eol
setting definitely helped clarify how EOL characters are handled by git.Things are about to change on the "eol conversion" front, with the upcoming Git 1.7.2:
A new config setting
core.eol
is being added/evolved:Other evolutions are being considered:
git 2.8 (March 2016) improves the way
core.autocrlf
influences the eol:See commit 817a0c7 (23 Feb 2016), commit 6e336a5, commit df747b8, commit df747b8 (10 Feb 2016), commit df747b8, commit df747b8 (10 Feb 2016), and commit 4b4024f, commit bb211b4, commit 92cce13, commit 320d39c, commit 4b4024f, commit bb211b4, commit 92cce13, commit 320d39c (05 Feb 2016) by Torsten Bögershausen (
tboegi
).(Merged by Junio C Hamano --
gitster
-- in commit c6b94eb, 26 Feb 2016)As torek adds in the comments:
For more on that, see "What is difference between autocrlf and eol".
Did some tests both on linux and windows. I use a test file containing lines ending in LF and also lines ending in CRLF.
File is committed , removed and then checked out. The value of core.autocrlf is set before commit and also before checkout. The result is below.
Here is my understanding of it so far, in case it helps someone.
core.autocrlf=true
andcore.safecrlf = true
You have a repository where all the line endings are the same, but you work on different platforms. Git will make sure your lines endings are converted to the default for your platform. Why does this matter? Let's say you create a new file. The text editor on your platform will use its default line endings. When you check it in, if you don't have core.autocrlf set to true, you've introduced a line ending inconsistency for someone on a platform that defaults to a different line ending. I always set safecrlf too because I would like to know that the crlf operation is reversible. With these two settings, git is modifying your files, but it verifies that the modifications are reversible.
core.autocrlf=false
You have a repository that already has mixed line endings checked in and fixing the incorrect line endings could break other things. Its best not to tell git to convert line endings in this case, because then it will exacerbate the problem it was designed to solve - making diffs easier to read and merges less painful. With this setting, git doesn't modify your files.
core.autocrlf=input
I don't use this because the reason for this is to cover a use case where you created a file that has CRLF line endings on a platform that defaults to LF line endings. I prefer instead to make my text editor always save new files with the platform's line ending defaults.
No, the @jmlane answer is wrong.
For
Checkin (git add, git commit)
:text
property isSet, Set value to 'auto'
, the conversion happens enen the file has been committed with 'CRLF'text
property isUnset
:nothing happens, enen forCheckout
text
property isUnspecified
, conversion depends oncore.autocrlf
autocrlf = input or autocrlf = true
, the conversion only happens when the file in the repository is 'LF', if it has been 'CRLF', nothing will happens.autocrlf = false
, nothing happensFor
Checkout
:text
property isUnset
: nothing happens.text
property isSet, Set value to 'auto
: it depends oncore.autocrlf
,core.eol
.core.eol
text
property isUnspecified
, it depends oncore.autocrlf
.2.1
2.2
text
property isUnspecified
Default behavior
So the Default behavior is
text
property isUnspecified
andcore.autocrlf = false
:Conclusions
text
property is set, checkin behavior is depends on itself, not on autocrlf