336

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?

Community
  • 1
  • 1
Rich
  • 6,129
  • 4
  • 30
  • 51
  • 1
    Would http://stackoverflow.com/questions/2333424/distributing-git-configuration-with-the-code/2354278#2354278 help? I has link to specific reasons for leaving `autocrlf` to false. – VonC May 13 '10 at 09:00
  • 3
    @VonC Thanks, but I am already able to dictate that all users in the company set autocrlf 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. – Rich May 13 '10 at 09:32
  • 4
    @VonC i.e. I'm not looking for reasons to set `autocrlf` to false. I'm looking for reasons to set it to true. – Rich May 13 '10 at 09:38
  • 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. – VonC May 13 '10 at 09:57
  • 12
    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`. – iconoclast Aug 07 '12 at 21:50
  • 1
    @iconoclast, `autocrlf = input` makes `stash --patch` fail with "Cannot remove worktree changes" – Piotr Findeisen Sep 24 '12 at 08:02
  • @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`? – iconoclast Sep 24 '12 at 13:57
  • @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? – Piotr Findeisen Sep 24 '12 at 21:19
  • @PiotrFindeisen: you can't stash *at all* with `autocrlf = input` or just with `--patch`? – iconoclast Sep 25 '12 at 14:13
  • DIdn't check. I can't live without `--stash` switch. – Piotr Findeisen Sep 25 '12 at 14:37
  • 7
    @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. – user1809090 Aug 01 '14 at 16:04
  • nb. the GitHub article so often cited https://help.github.com/articles/dealing-with-line-endings/ is actually based on an SO answer - http://stackoverflow.com/questions/1510798/trying-to-fix-line-endings-with-git-filter-branch-but-having-no-luck/1511273#1511273 - which partially explains this self-perpetuating confusion. – Ed Randall Feb 09 '17 at 14:02
  • man, it must totally be dependent on use case. @iconoclast 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. – blamb Oct 01 '20 at 23:03

5 Answers5

266

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"

VonC
  • 1,042,979
  • 435
  • 3,649
  • 4,283
  • 5
    @VonC 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? – Rich May 13 '10 at 10:45
  • @Rich I believe Git does eol conversion by default (i.e. if `autocrlf` is not set at all) – VonC May 13 '10 at 11:10
  • 15
    @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). – Michael Maddox Jul 09 '10 at 11:30
  • @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. – VonC Jul 09 '10 at 12:42
  • 3
    @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? – Rich Jul 14 '10 at 16:07
  • @Rich: I don't know the answer to your original question, but I did give you a +1 for the question as I think it's interesting and relevant. – Michael Maddox Jul 14 '10 at 17:08
  • @Michael: Thanks! We've set it to `false` here and I'll add my own answers if we come across any problems. – Rich Jul 27 '10 at 10:34
  • 56
    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. – Tower Jun 11 '12 at 16:01
  • 1
    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. – Paul d'Aoust Apr 09 '13 at 19:06
  • 6
    @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. – VonC Apr 10 '13 at 05:13
  • 1
    @VonC 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. – Paul d'Aoust Apr 17 '13 at 03:01
  • 3
    somehow the best explanation of how (not) to use autocrlf is found in hg docs http://mercurial.selenic.com/wiki/EolExtension (note the "last resort" warning) – OlegYch Jan 26 '14 at 14:01
  • +1 I agree. Also when working under windows, avoiding touching crlf is a good idea. Also eclipse emacs and most advanced editors/ide can deal with different platform line ending. – daitangio Mar 11 '15 at 11:55
  • 2
    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. – Jeremy Jul 17 '15 at 16:18
  • 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. – Minok Oct 23 '15 at 00:31
  • 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). – DarthPablo Dec 16 '15 at 15:16
  • @Minok 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. – Rich Dec 16 '15 at 15:31
  • @Tower 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. – code_dredd Oct 21 '17 at 03:44
  • @ray Still, you should be able to configure your Monodevelop editor: https://stackoverflow.com/a/24700026/6309, https://stackoverflow.com/a/9984943/6309, http://answers.unity3d.com/questions/424631/monodevelop-line-ending-settings-ignored.html – VonC Oct 21 '17 at 03:48
  • @VonC Indeed; I have no issues with the code editor itself, but thanks. – code_dredd Oct 21 '17 at 03:48
  • 1
    @VonC The answer says "you are better off leaving autocrlf to false" but does not mention how to enforce this via `.gitattributes`. Could you maybe add `* -text` so readers don't have to figure this out on their own? Also, maybe the answer should also provide the command for the local setting as well: `git config --global core.autocrlf false`. – Jens Bannmann Nov 01 '19 at 08:20
  • @JensBannmann I agree. I have edited both answers accordingly. – VonC Nov 01 '19 at 08:49
50

I am a .NET developer, and have used Git and Visual Studio for years. My strong recommendation is 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. A 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.

JGTaylor
  • 858
  • 7
  • 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! – Rich Jun 20 '16 at 09:04
  • 1
    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. :( – JGTaylor Jun 23 '16 at 11:48
  • 7
    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. – Tuncay Göncüoğlu Aug 18 '16 at 11:57
  • Perhaps it is possible to add a hook on the server to prevent these kinds of changes from being pushed. – Ed Randall Oct 02 '16 at 12:12
  • 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. :) – JGTaylor Oct 03 '16 at 15:46
  • 12
    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. – phuclv Nov 16 '16 at 09:38
  • 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. :) – JGTaylor Nov 16 '16 at 20:31
  • 8
    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. – quetzalcoatl Oct 20 '17 at 08:07
  • 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. – quetzalcoatl Oct 20 '17 at 08:09
  • I see the problem completely on Microsoft's site. Their system is the only one using stupid CRLF line breaks. – Bachsau Dec 03 '17 at 17:52
  • 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. – XDS Aug 20 '19 at 11:14
  • Posts like these remind me that we must treat line endings as first class citizens in code culture. – Jarretinha Apr 16 '21 at 01:06
12

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".

Rich
  • 6,129
  • 4
  • 30
  • 51
  • 2
    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). – Rich Jan 16 '12 at 16:50
  • 2
    Unfortunately corporate version control nazis disagree with it (LF on merge conflict markers) not being an issue. – Ilia G Dec 10 '13 at 15:16
  • 1
    I agree that LF on merge conflict markers should not be an issue. Those lines shouldn't be committed to the repo anyway. – rob Oct 09 '15 at 15:19
  • 1
    Note: starting git 2.8 (March 2016), merge markers will actually have CRLF line ending. See http://stackoverflow.com/a/35474954/6309 – VonC Feb 18 '16 at 07:11
0

For me.

Edit .gitattributes file.

add

*.dll binary

Then everything goes well.

Shinji
  • 1
  • 2
  • 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. – Rich Jul 31 '20 at 21:34
0

I am working on GitHub and I found this article helpful.

It describes the config of git autocrlf and the setting .gitattributes file.

Jeff
  • 56
  • 4