Git checkout files with LF line endings - windows

PSR-12 for PHP and Airbnb's ESLint config for React requires LF line endings over CRLF. I see in the ESLint docs that they recommend adding a .gitattributes file with content similar to this:
*.js text eol=lf
I checked the Git documentation and it mentions that using eol can make paths be considered dirty. What is meant by this? I also notice there's mentions of core.safecrlf later in the docs, so can these types of conversions cause irreversible problems?
Will I also need to set core.autocrlf to false so that .gitattributes takes effect?

When you set a file in text mode in Git, that tells Git that you want it to perform end-of-line conversion. That means that Git will always write the file into its internal storage with LF endings, and then check out the endings that are specified, whether that's due to .gitattributes or various configuration options.
If, however, the repository already contains files with CRLF line endings checked in, then setting the eol option will cause the file to be checked into the repository with LF endings, as mentioned above. This will make Git think the file is modified, which it is. That's what's meant by making "the paths to be considered dirty."
The easiest way to solve this problem is to add the entries to .gitattributes, add the .gitattributes file, and then run git add --renormalize . and then commit. That way, any files which had CRLF endings will be converted to LF endings in the repository.
You don't also need to set core.autocrlf in addition. That behavior is overridden by the .gitattributes file.

Related

Working on Windows, but getting "LF will be replaced by CRLF" when committing in Git

I am checking out from a repository where I am the only Windows user in a sea of Mac and Linux. My IDE is running on my Windows machine, and code is pushed to a VM. The code isn't synced back to the host. When I am ready to add / commit on my Windows host, I get the warning: LF will be replaced by CRLF message.
These are my Git settings :
core.symlinks=false
core.autocrlf=true
core.fscache=true
color.diff=auto
color.status=auto
color.branch=auto
color.interactive=true
help.format=html
http.sslcainfo=C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt
diff.astextplain.textconv=astextplain
rebase.autosquash=true
credential.helper=manager
core.editor='C:/Program Files/Notepad++/notepad++.exe' -multiInst -nosession
core.filemode=false
core.repositoryformatversion=0
core.filemode=false
core.bare=false
core.logallrefupdates=true
core.symlinks=false
core.ignorecase=true
I'm not sure why core.filemode=false is listed twice.
Is there a reason why I would be getting this warning on Windows? Am I doing something moronic in my settings (totally possible)? Or, does this make sense in this scenario, and if so, why?
Git has two places that line feeds can be controlled:
In the global config settings on your system
In the .gitattributes file that applies per repo/project. These settings will override the user's configuration settings.
In your Git settings your have core.autocrlf=true. Meaning you are telling Git to change the line ending to CRLF. You can change this to see if Git stops trying to change the line endings.
git config --global core.autocrlf input
A better approach may be to set the proper line endings in the .gitattributes file. This is committed to the repository in the root and it will overrides user's individual settings. This ensures that all users committing to the repo will have the proper line endings. Because it sounds like you are working on *nix based project it would probably be prudent to set the line endings to line feed. In the .gitattribute files you could have something like this.
# Set all files to have LF line endings
* text eol=lf
This link has a more detailed explanation of the options you can set in the file: https://help.github.com/articles/dealing-with-line-endings/
EDIT 1: Thought I add this from the actual Git documentation: https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration
core.autocrlf
If you’re programming on Windows and working with people
who are not (or vice-versa), you’ll probably run into line-ending
issues at some point. This is because Windows uses both a
carriage-return character and a linefeed character for newlines in its
files, whereas Mac and Linux systems use only the linefeed character.
This is a subtle but incredibly annoying fact of cross-platform work;
many editors on Windows silently replace existing LF-style line
endings with CRLF, or insert both line-ending characters when the user
hits the enter key.
Git can handle this by auto-converting CRLF line endings into LF when
you add a file to the index, and vice versa when it checks out code
onto your filesystem. You can turn on this functionality with the
core.autocrlf setting. If you’re on a Windows machine, set it to true
– this converts LF endings into CRLF when you check out code:
$ git config --global core.autocrlf true
If you’re on a Linux or Mac
system that uses LF line endings, then you don’t want Git to
automatically convert them when you check out files; however, if a
file with CRLF endings accidentally gets introduced, then you may want
Git to fix it. You can tell Git to convert CRLF to LF on commit but
not the other way around by setting core.autocrlf to input:
$ git config --global core.autocrlf input
This setup should leave you
with CRLF endings in Windows checkouts, but LF endings on Mac and
Linux systems and in the repository.
If you’re a Windows programmer doing a Windows-only project, then you
can turn off this functionality, recording the carriage returns in the
repository by setting the config value to false:
$ git config --global core.autocrlf false
There is a common misconception that on Windows, config.autocrlf=true will always make Git use CRLF line endings when checking out files. But if you read the Git documentation carefully, you'll notice:
[Setting config.autocrlf=true] does not force normalization of text files, but does ensure that text files that you introduce to the repository have their line endings normalized to LF when they are added, and that files that are already normalized in the repository stay normalized.
In other words, Git will only use CRLF when checking out files if the files have already been classified as text files when they were committed to the repository. By default, Git does not automatically classify files as text. Yes this is incredibly annoying, but it is a safety precaution so that by default, Git will never corrupt a binary file that it thought was text.
We can prevent this problem by telling Git to determine whether files are text. Either option below works:
In the Git attributes file, set the "text" attribute to "auto" for all files. This will configure Git to automatically determine whether a file is text. You can set this either once for each contributor (default location: $HOME/.config/git/attributes), or once for each repo (.gitattributes).
If you are on a Windows machine, set "core.autocrlf" to "true". This is the same as #1 but also sets core.eol to crlf, which is why this should only be done for Windows systems.
If you have a repo whose files were not classified as text, you may be getting a bunch of LF will be replaced by CRLF warnings whenever you commit changes to these files. To fix this problem once and for all, after performing the Git configuration mentioned above, run unix2dos on all the files (use find . -exec unix2dos {} \; in Git Bash or an equivalent Windows command), then commit them. The files will be re-classified as text all at once, you'll stop getting the warnings, and you'll also benefit from having CRLF line endings in your working directory. The remote repository will still use LF line endings, but future clones of the repo on Windows systems with the configuration mentioned above will use CRLF line endings locally as expected.

Make git Not Care About Line Endings of Files in My Working Tree

Let me clarify: I want git to not care about whether line endings are CRLF or LF on checkin/commit. I understand there is no way at the moment to make git not care if a file has mixed line endings, although I would love a workaround to this, just in case; I just want it not to care whether all line endings in a file are CRLF or LF.
I recently set many file extensions in my system .gitattributes file, /etc/gitattributes (using MSysGit), to tell git which extensions are usually text or binary. For most of the files I want git to think are text, I set the extension
*.extension text=auto
because this will tell git that files with these extensions should have the general system line endings. Now I am regretting that decision, as I am seeing how many files are, for one reason or another, automatically given LF line endings instead of CRLF. Now, after tinkering with this and other settings, I have been getting errors similar to
$ git add -A && git commit -m "signup/in/out now possible through passport"
fatal: LF would be replaced by CRLF in node_modules/mongoose/node_modules/ms/package.json
on a lot of files I try to check in. In this case, it seems to be npm that's causing these files to be created as LF instead of CRLF, but I'm sure there are many other causes.
To be honest, I personally don't care which type of line endings a specific file has, as long as I can read and edit these files in my editing tool(s) of choice, as the vast majority of the time the line endings don't have any special function besides being, well, line endings. If it really matters, I can always do a quick conversion with unix2dos or dos2unix. However, git is notoriously finicky with line endings, and I don't want it to accidentally mark a text file as binary or vice versa, hence why I have been changing all these defaults.
How do I make git check in all text files as LF-line-ended files, and check them out as CRLF, but not care whether they have CRLF or LF endings in my actual working tree? Alternatively, is there a way to have git convert all the text files with LF endings to CRLF in my working tree as well, instead of giving the warning and giving up?
EDIT It seems my issue was not with my gitattributes files, but with my core.safecrlf setting in my gitconfig.
My issue seems to be with another config setting I set in git, core.safecrlf. According to the accepted answer to this question, which clarified things in several blog posts on the subject, this setting checks to see if the files git is checking in or out will have their line endings changed. If it determines they will be changed, it aborts the operation. I didn't understand this setting before, but now that I've played around a bit, I think I do understand it.
From what I can tell by the playing around, it seems that this setting is only useful for binary files with extensions not specified in your gitattributes, as well as files where line endings actually have a meaning in the language you will be using to edit them. As an example, let's assume all files in this language have the extension .ext. If this language uses the symbol computers use to denote LF and/or the one they use to denote CRLF, git shouldn't convert these .ext files. I don't know of any languages like that, but if they exist, and if the programmer still wants git to interpret files written in these languages as text, the programmer should have a special attribute set in his/her gitattributes, instead of having *.ext text.
Other than these 2 types of files, I can't think of any other situation to use core.safecrlf=true. Therefore, until I encounter a situation like these, I will be having this setting unset, or perhaps set to warn.
In your .gitattributes, just add this line. It will always convert all line ending to CRLF when checkout no matter what it was before.
* text eol=crlf
see this http://git-scm.com/docs/gitattributes
Set to string value "crlf"
This setting forces Git to normalize line endings for this file on checkin and convert them to CRLF when the file is checked out.
git config autocrlf <option>
It can have options:
1) true: x -> LF -> CRLF
2) input: x -> LF -> LF
3) false: x -> x -> x

Git commits wrong newlines when using .gitattributes

I was having an issue where merge conflicts resulted in the entire file being a conflict. This ended up being that the local file's newlines all became unix-style newlines (LF) at the time of merge (before merge both development and feature branch had CRLF newlines when checked out).
If I ran
git rm --cached -r .
git add -A
no changes would show up with git status. But when I deleted the .gitattributes file and did another remove all / add all it resulted in certain files being updated with different new lines. For example for a 100 line file it would say 100 lines deleted, 100 lines added. After doing this to both branches the merges were fine.
.gitconfig autocrlf = true was set and .gitattributes file only had these lines. I would think the below lines would only affect merging strategry.
*.csproj -text merge=union
*.sln -text merge=union
Why would this .gitattributes change how new lines are committed?
Also with autocrlf set to true I'm not sure why the merge would be comparing LF's vs CRLF's unless maybe something in the .gitattributes was overriding it.
From https://help.github.com/articles/dealing-with-line-endings
Optionally, you can configure the way Git manages line endings on a
per-repository basis by configuring a special .gitattributes file.
This file is committed into the repository and overrides an
individual's core.autocrlf setting, ensuring consistent behavior for
all users, regardless of their Git settings. The advantage of a
.gitattributes file is that your line configurations are associated
with your repository
This makes it clear that .gitattributes is capable of overriding autocrlf, but there are no settings in it that tell it to do any eol conversion. Maybe there is some default that is implicitly used.
I realise this is an old question, but the answer might be useful for someone having a related issue.
The gitattributes file specifies -text for *.csproj and *.sln files. This means that for those files no EOL conversion should be done.
On the other hand, you also used the configuration autocrlf = true. This setting means: store the files with LF line endings in the Git repository and store the files with native line endings in the working directory.
So: before adding the gitattributes file, the *.csproj and *.sln files are stored with LF line endings in the Git repo, because of the autocrlf setting. After adding the gitattributes file and checking out those files in the working directory, no EOL conversion is done, and those files end up with LF line endings in the working directory.

Git core.safecrlf different behavior on files with same line endings

I have Windows machine with VS project and I use both Visual Studio and tools from Cygwin environment including Git. Sometimes I get different line endings in files after editing. I want simple solution to check files' line ending consistency before they go to the repo. Git's core.safecrlf is the right thing I suppose.
Now I have a strange behavior:
Files A and B with following parameters:
$file A
A: HTML document, UTF-8 Unicode text, with CRLF line terminators
$file B
B: HTML document, UTF-8 Unicode (with BOM) text, with CRLF line terminators
File A is already in repo, file B is new one. Note, both have CRLF line endings. Now try to stage them, core.safecrlf is true.
$git add A # ok
$git add B # fails
fatal: CRLF would be replaced by LF in B.
Am using core.safecrlf correctly? Or maybe I need to write hook to check files?
Notes:
tried with different file encodings (with and without BOM), no difference.
there's related core.autocrlf feature in Git, added it to tags (Stackoverflow has no tag for core.safecrlf)
git version 1.8.5.rc1.17.g0ecd94d (compiled from sources under Cygwin)
EDIT #1: checked out core.autocrlf - it was input. Changed to false, now I can add both files. Why?
According to your later edit core.autocrlf = input was the original setting. With this setting CRLF is converted to LF when checked in to the repository and is kept that way when checked out. This means a non Unix line endings aware editor like Notepad would mess up the appearance of a checked out version of the file. It would be one giant long line.
FWIW core.autocrlf = input is the preferred setting on Unix systems and using the default cygwin build probably set it that way. In Windows the recommended settings is core.autocrlf = true which is what msysgit recommends
core.safecrlf = true aborts the conversion of a file if checking out the file will result in a changed and possibly damaged file which would be the case if Notepad was the editor. This is why file B was aborted because it would be messed up in an editor like Notepad. The difference between core.SAFEcrlf and core.AUTOcrlf should be noted. It is one of the eyes glazing over issues in understanding git line endings
core.autocrlf = false is don't care mode. It will check in and check out the files exactly as they are, which is why the commits now work. This is not very smart and is not recommended because it causes problems if the files are edited on both Windows and Unix systems and also if another users core.autocrlf settings differ and change the file endings.
My own preference is to set core.autocrlf to input on Windows if all the Windows editors and other text file processing tools on the project are Unix line ending aware, otherwise set it to core.autocrlf = true for Windows and core.autocrlf = input for Unix. In any case this approach is outmoded by the superior method of the .gitattributes file.
The .gitattributes file method processes files based on the file name and is maintained in all users environments as it is checked out into the working directory like .gitignore. The settings for as many file names and types as are relevant to your project should be added to .gitattributes. Your configuration then falls back onto the local core.autocrlf and core.safecrlf settings if the file name is not matched in .gitattributes. Adding * text=auto at the top of .gitattributes will cause git to do a best guess on file names which are not matched by the later .gitattributes settings.
This web page, Mind the End of Your Line helped me understand the issue better. You might read for more background on the issue.
The CR LF line ending choices are not that easy to understand. There are two places for the descriptions in that it is covered both in Git-attributes and Git-config manuals.
Initially there were the autocrlf settings, and then there were the newer versions which have some potential incompatibilities (i.e. do unexpected things as you indicate).
I tend to set the eol=LF, which makes all text files be committed as LF line endings (you can set attributes as to which files are considered text) and then add the safecrlf for doing a round trip check.

Trying to commit Git files but getting :: fatal: LF would be replaced by CRLF in <some file in repo>

When I try to commit some changed files, I get the following error message with TortoiseGit
fatal: LF would be replaced by CRLF in <some file in the repo>
Now, before I get the usual LF vs CRLF answers, I know and understand what the debate is about. Secondly, I've also set my global settings to:
core.autocrlf true
Third, I've got a .gitattributes file.
So I -want- to make sure or files are forced to have CRLF.
What I don't understand is that it's saying FATAL and blocking me from continuing. A Warning? Sure! Do I know what I'm trying to do? I do!
I just want it to convert silently and STFU.
Alternatively, if it's forced to BLOCK me, is there a way I can update all files in the repo to be CRLF, so this warning is no longer issued?
These repos are private, so they will never be developed outside of Windows + Visual Studio.
How can I proceed?
You might want to set core.safecrlf to "warn", if you want only warning and not a fatal error.
From "git config" mange page:
core.safecrlf
If true, makes git check if converting CRLF is reversible when end-of-line conversion is active. Git will verify if a command modifies a file in the work tree either directly or indirectly.
For example, committing a file followed by checking out the same file should yield the original file in the work tree. If this is not the case for the current setting of core.autocrlf, git will reject the file.
The variable can be set to "warn", in which case git will only warn about an irreversible conversion but continue the operation.
CRLF conversion bears a slight chance of corrupting data.
When it is enabled, git will convert CRLF to LF during commit and LF to CRLF during checkout.
A file that contains a mixture of LF and CRLF before the commit cannot be recreated by git.
For text files this is the right thing to do: it corrects line endings such that we have only LF line endings in the repository.
But for binary files that are accidentally classified as text the conversion can corrupt data.
If you recognize such corruption early you can easily fix it by setting the conversion type explicitly in .gitattributes.
Right after committing you still have the original file in your work tree and this file is not yet corrupted. You can explicitly tell git that this file is binary and git will handle the file appropriately.
Unfortunately, the desired effect of cleaning up text files with mixed line endings and the undesired effect of corrupting binary files cannot be distinguished.
In both cases CRLFs are removed in an irreversible way. For text files this is the right thing to do because CRLFs are line endings, while for binary files converting CRLFs corrupts data.
I prefer identifying the exact files or types of file I want to force the eol with .gitattributes files only (with core.eol settings, which you have), and leave autocrlf to false.
In case of text fiels with mixed eol, this blog post suggests, for instance, to:
If you have Notepad++ installed in your computer, simply follow these steps.
Open the file that is having the Fatal issue.
Click Edit -> EOL Conversion then select Windows Format or to any that you’re having an issue committing.
Warning, if you have Git 2.17 or 2.18: a regression introduced in 8462ff4 ("convert_to_git(): safe_crlf/checksafe becomes int conv_flags", 2018-01-13, Git 2.17.0) back in Git 2.17 cycle caused autocrlf rewrites to produce a warning message despite setting safecrlf=false.
See commit 6cb0912 (04 Jun 2018) by Anthony Sottile (asottile).
(Merged by Junio C Hamano -- gitster -- in commit 8063ff9, 28 Jun 2018)
git config --global core.safecrlf false
This will disable the crlf fatal warning.
git config core.autocrlf false
git config core.safecrlf false
Since your repo is private, you can set git-config like this:
git config --global core.autocrlf false
This will solve your problem.If you have any further question,
You can read the 《Pro git》:
If you’re a Windows programmer doing a Windows-only project, then you can turn off this functionality, recording the carriage returns in the repository by setting the config value to false:
$ git config --global core.autocrlf false
But when collaborating, you should better do these below:
add .gitattributes, Github help-Dealing with line endings will be helpful.
git config --global core.safecrlf true
windows:git config --global core.autocrlf true
mac or linux:git config --global core.autocrlf input
You may want to Read Git docs-git config for more info.
git config --global core.autocrlf false will checkin files with CRLF, that is not used to.
I've noticed on Windows, that with core.autocrlf true git doesn't like files with LF and core.autocrlf input doesn't like CRLF.
So: commit CRLF files with core.autocrlf true and LF files with core.autocrlf input (or convert them to CRLF).
Usually files with LF is autogenerated by code generators (e.g. https://start.spring.io or http://yeoman.io/)
With .gitattributes file, use
*.h text=auto
*.cpp text=auto
*.txt text=auto
as is documented in
https://git-scm.com/docs/gitattributes.

Resources