Why should I use core.autocrlf=true in Git?
Asked Answered
T

5

459

I have a Git repository that is accessed from both Windows and OS X, and that I know already contains some files with CRLF line-endings. As far as I can tell, there are two ways to deal with this:

  1. Set core.autocrlf to false everywhere,

  2. Follow the instructions here (echoed on GitHub's help pages) to convert the repository to contain only LF line-endings, and thereafter set core.autocrlf to true on Windows and input on OS X. The problem with doing this is that if I have any binary files in the repository that:

    1. are not correctly marked as binary in gitattributes, and
    2. happen to contain both CRLFs and LFs,

    they will be corrupted. It is possible my repository contains such files.

So why shouldn't I just turn off Git's line-ending conversion? There are a lot of vague warnings on the web about having core.autocrlf switched off causing problems, but very few specific ones; the only that I've found so far are that kdiff3 cannot handle CRLF endings (not a problem for me), and that some text editors have line-ending issues (also not a problem for me).

The repository is internal to my company, and so I don't need to worry about sharing it with people with different autocrlf settings or line-ending requirements.

Are there any other problems with just leaving line-endings as-is that I am unaware of?

Tshirt answered 13/5, 2010 at 8:50 Comment(13)
Would #2333924 help? I has link to specific reasons for leaving autocrlf to false.Arteriole
@Arteriole Thanks, but I am already able to dictate that all users in the company set <code>autocrlf</code> to false and currently believe that to be the best option. But I want to know if there are any reasons why I shouldn't do that, because I can find there's a lot of people (e.g. GitHub) that say I autocrlf should be set but no actual specifics as to why.Tshirt
@Arteriole i.e. I'm not looking for reasons to set autocrlf to false. I'm looking for reasons to set it to true.Tshirt
ok (I was mislead by the "just leaving line-endings as-is" last question, which is "autocrlf set to false). I have written an answer to begin to address the opposite (set to true), but nothing very definitive yet.Arteriole
Why not use autocrlf = input: it seems to be the perfect resolution between the two extremes: you keep your repo clean from CRLF crap, and locally Windows developers can use whatever they want without their local files having anything magic done automatically to them. (They may want LF locally for various reasons, so true is bad, in my opinion.) I can't see any downsides to using autocrlf = input.Latona
@iconoclast, autocrlf = input makes stash --patch fail with "Cannot remove worktree changes"Kweilin
@PiotrFindeisen: very interesting. So there's definitely a downside. It sounds to me like a bug, though. Does it only fail when Git is translating between line endings for you, or does it always fail if you use autocrlf = input?Latona
@iconoclast, I did not test this extensively. Today i found only that i cannot stash until i remove autocrlf setting. The problematic file was stored with CRLF in the repo -- maybe this is unsupported combination?Kweilin
@PiotrFindeisen: you can't stash at all with autocrlf = input or just with --patch?Latona
DIdn't check. I can't live without --stash switch.Kweilin
@iconclast, one reason I've run into is if you build distributions that include both Windows batch files and Unix shell scripts. You want to use the correct line ending in each case, and this is harder to do if Git is swizzling things around even after you explicitly set them one way or the other.Breathing
nb. the GitHub article so often cited help.github.com/articles/dealing-with-line-endings is actually based on an SO answer - #1511298 - which partially explains this self-perpetuating confusion.Cooler
man, it must totally be dependent on use case. @Latona i think the same way as you, and backup the decision to use input always, so that win users dont have to worry about, and so that its cleaned on commit on my mac. it causes major binary issues without.Reynolds
A
363

The only specific reasons to set autocrlf to true are:

  • avoid git status showing all your files as modified because of the automatic EOL conversion done when cloning a Unix-based EOL Git repo to a Windows one (see issue 83 for instance)
  • and your coding tools somehow depends on a native EOL style being present in your file:

Unless you can see specific treatment which must deal with native EOL, you are better off leaving autocrlf to false (git config --global core.autocrlf false).

Note that this config would be a local one (because config isn't pushed from repo to repo)

If you want the same config for all users cloning that repo, check out "What's the best CRLF handling strategy with git?", using the text attribute in the .gitattributes file.

Example:

*.vcproj    text eol=crlf
*.sh        text eol=lf

Note: starting git 2.8 (March 2016), merge markers will no longer introduce mixed line ending (LF) in a CRLF file.
See "Make Git use CRLF on its “<<<<<<< HEAD” merge lines"

Arteriole answered 13/5, 2010 at 9:55 Comment(18)
@Arteriole Thanks! That helps me feel more confident that it's safe for me to use autocrlf=false. Out of interest, do you know why git still does eol conversion even if you have autocrlf set to false?Tshirt
@Tshirt I believe Git does eol conversion by default (i.e. if autocrlf is not set at all)Arteriole
@VonC: I don't think this answer is correct. Using core.autocrlf=true on Windows works as expected. All files from the repo (which should have LF line endings in this scenario) are converted to CRLF line endings on checkout to a Windows PC. All files are converted back to LF line endings on commit from a Windows PC. The way to get in trouble is to checkout initially to a Windows PC with the wrong core.autocrlf setting (which is entirely too easy to do).Stickinthemud
@Michael: I believe the issue was mainly when used in conjunction with git svn: the result had a git status reporting many differences between the index and HEAD. For a classic clone (no svn), you are right.Arteriole
@Michael So in that case is the only reason not to use core.autocrlf=false in my scenario be if I had some tool/editor that would get confused by the line-endings?Tshirt
I would definitely use false, I've never been a big fan of automatic or magic things happening in the background. Just use \n and UTF-8 everywhere and you will be fine. If some nut-head does not understand that there are conventions and rules and forgets to use UTF-8 or \n, then someone converts them manually and slaps his face.Anders
If you're unfortunate enough to be working on a Visual Studio 6 project or something that includes a Wise Installer script (version 9 at least) you'll definitely want this set to auto -- those are two tools that expect CRLFs.Insane
@Pauld'Aoust I would still prefer to specify the type of file needing that CRLF through core.eol attributes in a .gitattributes file, rather than using this global core.autocrlf setting which applies indiscriminately to all files.Arteriole
@Arteriole Fair enough; I'd prefer not to let Git make those decisions for me either -- I've just found that everything works pretty well for me when core.autocrlf is true.Insane
somehow the best explanation of how (not) to use autocrlf is found in hg docs mercurial.selenic.com/wiki/EolExtension (note the "last resort" warning)Tully
It becomes even more important on projects where your source files may expect and create CRLF line endings, but checkout of certain files require you to preserve line endings like bash scripts. I work on a software that is targeted for windows development, but also has bash scripts that we want untouched, but may be edited and version controlled. These mixed line ending means we either need autocrlf=false or need to create .gitattributes for specific files.Sierra
The setting to use depends on your particular client machine, as the GIT docs indicate. Regardless of where the repo sits, if your editing on an MS Windows box, you likely want it set to AUTO so the files put on your windows file system have CR-LF endings so you can edit files with simple text editors. If your working and enditing on a unix/linux/osx system then you want it it set to INPUT, so the CR-LF are converted to LF when the file is added to the repo from the file system, but it leaves the LF form in place when writing to your file system.Curcuma
We use a mix of Windows and Mac clients, and it seems the autocrlf setting is true on Windows and blank on a Mac (mix of GIT clients).Outbreed
@Curcuma I think you might need to re-read the question. You're just reiterating the standard advice, but that won't work for the repository in question.Tshirt
@Anders MonoDevelop solution and project files (among other config files) always seem to use CRLF and there's no built-in option to change that AFAIK (using latest v6.x). It's extremely annoying having to see those in git diff outputs.Hua
@ray Still, you should be able to configure your Monodevelop editor: https://mcmap.net/q/11255/-monodevelop-embedded-resource-line-ending-crlf-converted-to-lf, https://mcmap.net/q/11256/-monodevelop-convert-line-ending-dialog, answers.unity3d.com/questions/424631/…Arteriole
At the moment, I suggest to set autocrlf=True on Windows, so that when you commit the changes, the CRLF is automatically converted to LF. In this case, you always have LF endings in git repository.Hospice
@Hospice It is better to use .gitattributes for managing eol policy. (eol = end of line)Arteriole
A
71

I am a .NET developer and have used Git and Visual Studio for years. My strong recommendation is to set line endings to true. And do it as early as you can in the lifetime of your Repository.

That being said, I HATE that Git changes my line endings. Source control should only save and retrieve the work I do, it should NOT modify it. Ever. But it does.

What will happen if you don't have every developer set to true, is ONE developer eventually will set to true. This will begin to change the line endings of all of your files to LF in your repo. And when users set to false check those out, Visual Studio will warn you, and ask you to change them. You will have 2 things happen very quickly. One, you will get more and more of those warnings, the bigger your team the more you get. The second, and worse thing, is that it will show that every line of every modified file was changed(because the line endings of every line will be changed by the true guy). Eventually, you won't be able to track changes in your repo reliably anymore. It is MUCH easier and cleaner to make everyone keep to true than to try to keep everyone false. As horrible as it is to live with the fact that your trusted source control is doing something it should not. Ever.

Amusing answered 10/6, 2016 at 13:23 Comment(13)
My company is small enough that that we can easily mandate that false is used everywhere, and I would've thought larger companies could do this via policy, but I guess this is a legitimate reason for using "true", so I'm upvoting anyway. Thanks!Tshirt
The problem with doing this with a policy(file enforced) is that on a windows machine you can have a local, a global, and a hidden config file(ProgramData/Git/Confg). You can enforce the local by checking it into the repo, but the Global AND the hidden files take precedence. Also it is possible to have local and global(or hidden) be different. If they are, they will conflict with each other on the SAME machine causing line ending errors where there are none. This is a pain to track down. :(Amusing
exactly what I think. its not the job of a source control to mess with code files as it pleases. line endings should simply be a concern of editing tools, nothing more.Mm
Perhaps it is possible to add a hook on the server to prevent these kinds of changes from being pushed.Cooler
It might be. I am not familiar with server hooks for .git. What I have used is denying certain users write permissions to key branches like master, and enforcing pull request to prevent horrible check-ins. The management and setup of a consistent line ending scheme is not terribly hard for even large teams. And is well worth it. If you are familiar with a good way to add the hooks you allude to, please leave a link in a comment. :)Amusing
If your project is Windows-only then there's no problem. However if you or your colleagues work on a *nix platform then your "strong recommendation" will cause problems. Try running a bash, perl or python script with the shebang ending with \r\n and you'll see.Notochord
I agree 100%. That is why I started my Answer with the description of my most common environment. I understand that non Visual Studio on Windows user would benefit more from one of the other answers. But on Windows, and in Visual Studio it is very important to keep my points in mind. :)Amusing
The situation you described as is not problem of GIT, set the setting to FALSE as it usually should be and it's gone. Instad, it is a problem in the team work. What does it mean "eventually one developer sets true"? Why would you allow them that in the first place? when you set them up for accessing git repo, then just like you don't allow polluting certain areas with different langs (so anyone working on that can read it), or just like you keep branches/merges/rebases/etc along the chosen policy, they should get a clear rule: set correct crlf.Milagro
and if you're worried about people ignoring that rule, set a pre-commit hook that will count number of [^\r]\n and number of \r\n before and after the commit, and make it fail when the difference is over, say, relative, over 70% of lines in the file, leaving a small back door to make it pass if absolute number of is <=5, so small line-ending fixes can be done.Milagro
I see the problem completely on Microsoft's site. Their system is the only one using stupid CRLF line breaks.Dikdik
As a stop gap solution you can have your build system place a pre-commit git-hook which will stop every commit dead on its tracks if it detects that the autocrlf option is set to true in the config file of your git pull. This will probably solve the issue for good.Saurischian
Posts like these remind me that we must treat line endings as first class citizens in code culture.Archespore
You can enforce these rules by settings .gitattributes with * text=autoOverture
T
13

Update 2:

Xcode 9 appears to have a "feature" where it will ignore the file's current line endings, and instead just use your default line-ending setting when inserting lines into a file, resulting in files with mixed line endings.

I'm pretty sure this bug didn't exist in Xcode 7; not sure about Xcode 8. The good news is that it appears to be fixed in Xcode 10.

For the time it existed, this bug caused a small amount of hilarity in the codebase I refer to in the question (which to this day uses autocrlf=false), and led to many "EOL" commit messages and eventually to my writing a git pre-commit hook to check for/prevent introducing mixed line endings.

Update:

Note: As noted by VonC, starting from Git 2.8, merge markers will not introduce Unix-style line-endings to a Windows-style file.

Original:

One little hiccup that I've noticed with this setup is that when there are merge conflicts, the lines git adds to mark up the differences do not have Windows line-endings, even when the rest of the file does, and you can end up with a file with mixed line endings, e.g.:

// Some code<CR><LF>
<<<<<<< Updated upstream<LF>
// Change A<CR><LF>
=======<LF>
// Change B<CR><LF>
>>>>>>> Stashed changes<LF>
// More code<CR><LF>

This doesn't cause us any problems (I imagine any tool that can handle both types of line-endings will also deal sensible with mixed line-endings--certainly all the ones we use do), but it's something to be aware of.

The other thing* we've found, is that when using git diff to view changes to a file that has Windows line-endings, lines that have been added display their carriage returns, thus:

    // Not changed

+   // New line added in^M
+^M
    // Not changed
    // Not changed

* It doesn't really merit the term: "issue".

Tshirt answered 16/1, 2012 at 16:50 Comment(4)
N.B. When Visual Studio encounters such a file, it offers to normalize the line-endings for you. Picking either Windows line-endings or electing not to normalize the line-endings works fine (as VS still displays it correctly the offending lines will have been deleted once the conflict has been resolved).Tshirt
Unfortunately corporate version control nazis disagree with it (LF on merge conflict markers) not being an issue.Touchmenot
I agree that LF on merge conflict markers should not be an issue. Those lines shouldn't be committed to the repo anyway.Birkner
Note: starting git 2.8 (March 2016), merge markers will actually have CRLF line ending. See https://mcmap.net/q/11231/-make-git-use-crlf-on-its-quot-lt-lt-lt-lt-lt-lt-lt-head-quot-merge-linesArteriole
B
0

For me.

Edit .gitattributes file.

add

*.dll binary

Then everything goes well.

Burdelle answered 24/7, 2020 at 3:32 Comment(1)
Unfortunately, there are many binary files that are not DLLs in my repository: in order to be certain I'd got the correct list of file extensions to add to .gitattributes would require reviewing tens of thousands of files.Tshirt
I
0

In our project we declared necessity of setting autocrlf to input value. Here is why you may be interested in this:

  • Your project runs in Linux/Unix environment and developers are writing code in Windows. During push CRLF is transformed into LF automatically, thus you just need to checkout Git repo on Unix server and everything will be good out of the box.
  • Sometimes developers upload configuration from Windows machines to servers manually using WinSCP. This leads to CRLF line endings on Unix machines and failed app starts. "input" value partially eliminates the number of such cases

The issues we faced not long ago:

  • If the line endings are set to CR (not CRLF) on DEV's machine, during push they won't be transformed to LF and will stay CR in GIT repository. Do checks of line-endings thoroughly
Isometrics answered 13/12, 2021 at 11:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.