74

I don't understand the complexities related to CrLf settings in git: core.autocrlf, core.safecrlf

I'm developing a cross-platform project in a team and would like both Windows and Linux developers to be able to work together without git marking files as modified just because of line ending style.

What do the various settings mean? What would be the consequences of choosing any of the options? And what would be the best solution for my case?

Yes, I'm aware of this question and the answers there were not insightful, thus not helpful.

Community
  • 1
  • 1
Jonathan
  • 84,911
  • 94
  • 244
  • 345
  • Other related questions: http://stackoverflow.com/questions/2016673/definitive-recommendation-for-git-autocrlf-settings and http://stackoverflow.com/questions/1249932/git-1-6-4-beta-on-windows-msysgit-unix-or-dos-line-termination – Cascabel Nov 15 '10 at 07:22
  • Example of autocrlf side-effect: http://stackoverflow.com/questions/2016404/git-status-shows-modifications-git-checkout-file-doesnt-remove-them – VonC Aug 23 '11 at 05:46
  • 1
    Just to make you feel more comfortable: nobody fully does :) – eckes Jul 03 '17 at 22:13

3 Answers3

99

The three values for autocrlf:

  • true - when content goes into the repository (is committed), its line endings will be converted to LF, and when content comes out of the repository (is checked out), the line endings be converted to CRLF. This is in general meant for clueless windows users/editors. Given the assumption that an editor (or user) is going to create files with CRLF endings, and will freak out if it sees normal LF endings, but that you want LF endings in the repo, this will hopefully cover you. It's possible for things to go awry, though. There are examples of spurious merge conflicts and reports of modified files in the linked questions.

  • input - when content goes into the repository, its line endings will be converted to LF, but content is left untouched on the way out. This is basically in the same realm as true, with the assumption that the editors actually can deal with LF endings correctly; you're just guarding against the possibility of accidentally creating a file with CRLF endings.

  • false - git doesn't deal with line endings at all. It's up to you. This is what a lot of people recommend. With this setting, if a file's line endings are going to be messed with, you'll have to be aware of it, so merge conflicts are a lot less likely (assuming informed users). Educating developers about how to use their editors/IDEs can pretty much take care of the problem. All of the editors I've seen designed for programmers are capable of dealing with this if configured properly.

Note that autocrlf will not affect content which is already in the repository. If you've committed something with CRLF endings previously, they'll stay that way. This is a very good reason to avoid depending on autocrlf; if one user doesn't have it set, they can get content with CRLF endings into the repo, and it'll stick around. A stronger way to force normalization is with the text attribute; setting it to auto for a given path will mark it for end-of-line normalization, assuming git decides the content is text (not binary).

A related option is safecrlf, which is basically just a way to make sure you don't irreversably perform CRLF conversion on a binary file.

I don't have a ton of experience dealing with Windows issues and git, so feedback about implications/pitfalls is certainly welcome.

Yuval Adam
  • 149,388
  • 85
  • 287
  • 384
Cascabel
  • 422,485
  • 65
  • 357
  • 307
  • thank you for a clear and detailed answer! A few questions: 1) Is text attr part of the repo? If a new programmer would clone it, would he receive the attr with it? 2) What would be a motivation to be aware of newline styles? 3) Assuming there isn't one, from your explanations, I should a) set autocrlf=true b) set text attr=auto on the root path of the repo and c) set safecrlf=?? 4) If I do set autocrlf=input, and "touch" the file with an IDE which is not configured well (probably changing LFs to CRLFs), will git see that file as modifid? – Jonathan Nov 15 '10 at 15:00
  • 1
    @Jonathan: (1) Have a look at the linked gitattributes manpage. Attributes are configured in .gitattributes files which can be tracked just like any other file. (2) Configuring your IDE to generate the right kind of output is a one-time thing, and it's totally essential - what about consistent indentation, spacing and formatting? Being aware means no surprises. (3a,b) Setting the text attribute to auto for *everything* should make the autocrlf setting unnecessary anyway, unless someone has managed to pick an editor (notepad?) which simply can't handle LFs. It's a safer way to do it. – Cascabel Nov 15 '10 at 15:04
  • @Jonathan: (3c) Enabling safecrlf is probably a good idea in any repo with tracked binary files and some kind of line ending conversion going on. (4) I *think* that in that case, you shouldn't see modifications - but I've seen plenty of people mentioning spurious indications of modified files. – Cascabel Nov 15 '10 at 15:07
  • Following your links on SA, I keep reading people suggesting keeping autocrlf=false, from your original answer I take it you also are inclined to autocrlf=false. Guess I'll have to configure my IDE + understand WTF's going on + convert all my current files to LF with some tool I'll find online... – Jonathan Nov 15 '10 at 15:16
  • @Jonathan: Online? The `dos2unix` (packaged as `fromdos` in some systems, I think) is the standard way to do that. And yeah, I would really recommend not using autocrlf; if you want to try to normalize line endings, the text gitattribute is a much cleaner way to go, and I believe it's been improved in recent versions of git. – Cascabel Nov 15 '10 at 15:24
  • A better explanation than even the Pro Git book http://git-scm.com/book/ch7-1.html#Formatting-and-Whitespace. Thank you! – Drew LeSueur Jun 06 '13 at 14:12
12

I explored 3 possible values for commit and checkout cases and this is the resulting table:

╔═══════════════╦══════════════╦══════════════╦══════════════╗
║ core.autocrlf ║     false    ║     input    ║     true     ║
╠═══════════════╬══════════════╬══════════════╬══════════════╣
║   git commit  ║ LF => LF     ║ LF => LF     ║ LF => LF     ║
║               ║ CR => CR     ║ CR => CR     ║ CR => CR     ║
║               ║ CRLF => CRLF ║ CRLF => LF   ║ CRLF => LF   ║
╠═══════════════╬══════════════╬══════════════╬══════════════╣
║  git checkout ║ LF => LF     ║ LF => LF     ║ LF => CRLF   ║
║               ║ CR => CR     ║ CR => CR     ║ CR => CR     ║
║               ║ CRLF => CRLF ║ CRLF => CRLF ║ CRLF => CRLF ║
╚═══════════════╩══════════════╩══════════════╩══════════════╝

I would recommend to use core.autocrlf = input across all platforms. In this case if Git faces CRLF it will implicitly convert it into LF, and existing files with LF remain as is.

pratt
  • 1,045
  • 11
  • 15
  • 1
    Did you do these experiments on a Windows box or a Unix box? – Edward Falk Jan 13 '17 at 00:34
  • 1
    @EdwardFalk, `core.autocrlf` behavior does not depend on OS type. But if I'm not mistaken default value on Windows is `true` and on Linux - `input`. One more thing that may cause issues is that most IDEs on Windows are configured to use CRLF by default for new files and on Linux - LF. – pratt Jan 21 '17 at 13:54
  • I think you switched things around for `input` and `true`. The table by Srikanth Popuri below looks correct to me. – Gandalf Saxe Jul 30 '18 at 17:16
  • @GandalfSaxe looks like you're right. Let me fix it – pratt Jul 31 '18 at 15:54
4

FYI., By default, Line ending in Windows will take CRLF and Linux will take LF. Please find the below table for clear understanding.

╔═══════════════╦══════════════╦══════════════╦══════════════╗
║ core.autocrlf ║    false     ║    input     ║    true      ║
║               ║ Win => Unix  ║ Win => Unix  ║ Win => Unix  ║
╠═══════════════╬══════════════╬══════════════╬══════════════╣
║   git commit  ║ LF => LF     ║ LF => LF     ║ LF => LF     ║
║               ║ CR => CR     ║ CR => CR     ║ CR => CR     ║
║               ║ CRLF => CRLF ║ *CRLF => LF  ║ *CRLF => LF  ║
╠═══════════════╬══════════════╬══════════════╬══════════════╣
║  git checkout ║ LF => LF     ║ LF => LF     ║ *LF => CRLF  ║
║               ║ CR => CR     ║ CR => CR     ║ CR => CR     ║
║               ║ CRLF => CRLF ║ CRLF => CRLF ║ CRLF => CRLF ║
╚═══════════════╩══════════════╩══════════════╩══════════════╝

In the above tabular information, the symbol * highlights the differences between Windows and Unix. At a glance, below is the CLRF information based on the OS platforms:


For Windows users

  • If windows users working with cross-platform projects, It MUST be core.autocrlf=true for Windows machines and core.autocrlf=input for Unix machines.
  • If windows users work with Only Windows projects, It can be both core.autocrlf=true or core.autocrlf=false. But core.autocrlf=input will result in issues in this case.

For Unix users (Linux / Mac OS)

  • If Unix users working with cross-platform projects, It MUST be core.autocrlf=true for Windows machines and core.autocrlf=input for Unix machines.
  • If Unix users work with Only Unix projects, It can be both core.autocrlf=input or core.autocrlf=false. But core.autocrlf=true will result in issues in this case.

For same OS users

  • For a pure Windows project or pure Unix project, it can be core.autocrlf=false.