ChatGPT解决这个技术问题 Extra ChatGPT

Git replacing LF with CRLF

On a Windows machine, I ran added some files using git add. I got warnings saying:

LF will be replaced by CRLF

What are the ramifications of this conversion?

@apphacker because standardising line-endings is less annoying than having to change them yourself when diffing two files. (And of course, if you disagree, then you can keep the core.autocrlf feature off).
why would the line endings be different unless the entire line was touched
I often touch lots of lines, because I'm experimenting with different ideas, adding trace statements to see how they work, etc. Then I might want to only commit a change to two or three lines and have git completely ignore the others because I had put them back they way I found them (or so I thought).
@MatrixFrog: your editor seems broken, unable to autodetect line endings. Which is it? I work on hybrid projects which must have some LF files and some other CRLF files in the same repo. Not a problem for any modern editor. Having version control (or file transfer) mess with line endings to work around editor limitations is the worst idea ever - obvious from the mere length of the explanations below.
The only modern editor I know about that does the wrong thing is Visual Studio. Visual Studio will happily open a file with LF line endings. If you then insert new lines, it will insert CRLF, and save out mixed line endings. Microsoft refuses to fix this, which is a pretty big blemish on an otherwise pretty good IDE :--(

3
35 revs, 10 users 61%

These messages are due to an incorrect default value of core.autocrlf on Windows.

The concept of autocrlf is to handle line endings conversions transparently. And it does!

Bad news: the value needs to be configured manually.

Good news: it should only be done one time per Git installation (per project setting is also possible).

How autocrlf works:

core.autocrlf=true:      core.autocrlf=input:     core.autocrlf=false:

     repository               repository               repository
      ^      V                 ^      V                 ^      V
     /        \               /        \               /        \
crlf->lf    lf->crlf     crlf->lf       \             /          \
   /            \           /            \           /            \

Here crlf = win-style end-of-line marker, lf = unix-style (also used on Mac since Mac OS X).

(pre-osx cr is not affected for any of three options above.)

When does this warning show up (under Windows)?

    – autocrlf = true if you have unix-style lf in one of your files (= RARELY),
    – autocrlf = input if you have win-style crlf in one of your files (= almost ALWAYS),
    – autocrlf = false – NEVER!

What does this warning mean?

The warning "LF will be replaced by CRLF" says that you (having autocrlf=true) will lose your unix-style LF after commit-checkout cycle (it will be replaced by windows-style CRLF). Git doesn't expect you to use unix-style LF under Windows.

The warning "CRLF will be replaced by LF" says that you (having autocrlf=input) will lose your windows-style CRLF after a commit-checkout cycle (it will be replaced by unix-style LF). Don't use input under Windows.

Yet another way to show how autocrlf works

1) true:             x -> LF -> CRLF
2) input:            x -> LF -> LF
3) false:            x -> x -> x

where x is either CRLF (windows-style) or LF (unix-style) and arrows stand for

file to commit -> repository -> checked out file

How to fix

The default value for core.autocrlf is selected during Git installation and stored in system-wide gitconfig (%ProgramFiles(x86)%\git\etc\gitconfig on Windows, /etc/gitconfig on Linux). Also there're (cascading in the following order):

   – "global" (per-user) gitconfig located at ~/.gitconfig, yet another
   – "global" (per-user) gitconfig at $XDG_CONFIG_HOME/git/config or $HOME/.config/git/config and
   – "local" (per-repo) gitconfig at .git/config in the working directory.

So, write git config core.autocrlf in the working directory to check the currently used value and

   – git config --system core.autocrlf false            # per-system solution
   – git config --global core.autocrlf false            # per-user solution
   – git config --local core.autocrlf false              # per-project solution

Warnings

    – git config settings can be overridden by gitattributes settings.
    – crlf -> lf conversion only happens when adding new files, crlf files already existing in the repo aren't affected.

Moral (for Windows):

    - use core.autocrlf = true if you plan to use this project under Unix as well (and unwilling to configure your editor/IDE to use unix line endings),
    - use core.autocrlf = false if you plan to use this project under Windows only (or you have configured your editor/IDE to use unix line endings),
    - never use core.autocrlf = input unless you have a good reason to (eg if you're using unix utilities under Windows or if you run into makefiles issues),

PS What to choose when installing Git for Windows?

If you're not going to use any of your projects under Unix, don't agree with the default first option. Choose the third one (Checkout as-is, commit as-is). You won't see this message. Ever.

PPS: My personal preference is configuring the editor/IDE to use unix-style endings, and setting core.autocrlf to false.


This is so confusing. I have LF set in my editor. All the repo code uses LF. global autocrlf is set to false and the core gitconfig in my home dir is set to false. But I still get message LF being replaced with CRLF
If you've configured your editor to use Unix style endings, why not set core.autocrlf to input? From what I gathered from your answer, setting it to input makes sure the repository and the working directory always has unix-style line endings. Why would you never want that in Windows?
Something's odd though. I have core.autocrlf set to false in both global and local config, but I still get the warning when trying to commit. git version is 2.7.0
Figured it out: .gitattributes can override the config settings.
@AntonyHatchkins The profit is that input will convert my line endings, should I ever accidentally have a CRLF somewhere (maybe you once make a quick edit in Notepad instead of your nicely configured IDE!), while not affecting all the intentional LFs. The downside of using false would be that if I ever have an accidental CRLF, I might accidentally commit it to the repo. input would prevent that! So input > false, no?
P
Peter Mortensen

Git has three modes of how it treats line endings:

# This command will print "true" or "false" or "input"
git config core.autocrlf

You can set the mode to use by adding an additional parameter of true or false to the above command line.

If core.autocrlf is set to true, that means that any time you add a file to the Git repository that Git thinks is a text file, it will turn all CRLF line endings to just LF before it stores it in the commit. Whenever you git checkout something, all text files automatically will have their LF line endings converted to CRLF endings. This allows development of a project across platforms that use different line-ending styles without commits being very noisy, because each editor changes the line ending style as the line ending style is always consistently LF.

The side effect of this convenient conversion, and this is what the warning you're seeing is about, is that if a text file you authored originally had LF endings instead of CRLF, it will be stored with LF as usual, but when checked out later it will have CRLF endings. For normal text files this is usually just fine. The warning is a "for your information" in this case, but in case Git incorrectly assesses a binary file to be a text file, it is an important warning, because Git would then be corrupting your binary file.

If core.autocrlf is set to false, no line-ending conversion is ever performed, so text files are checked in as-is. This usually works ok, as long as all your developers are either on Linux or all on Windows. But in my experience I still tend to get text files with mixed line endings that end up causing problems.

My personal preference is to leave the setting turned ON, as a Windows developer.

See git-config for updated information that includes the "input" value.


As said here (stackoverflow.com/questions/1249932/…), I would respectfully disagree and leave that setting to OFF (and use Notepad++ or any other editor able to deal with -- and leave as it is -- whatever end line character it finds)
I like this answer, and prefer to leave autocrlf set to true. As an alternative, is there a way to kill the warning messages automatically?
It would be nice to augment this well-written answer with a comparison to the core.eol settings, perhaps in concert with .gitattributes configuration. I've been trying to figure out the differences and overlaps through experimentation, and it's very confusing.
For a more permanent solution change your .gitconfig to: [core] autocrlf = false
Is there any easy way to just squelch the warning? I want it to true and know that I have set it to true. I don't need to see all the warnings all the time... It's OK, really... :p
P
Peter Mortensen

If you already have checked out the code, the files are already indexed. After changing your Git settings, say by running:

git config --global core.autocrlf input

You should refresh the indexes with

git rm --cached -r .

And rewrite the Git index with

git reset --hard

Note: this will remove your local changes. Consider stashing them before you do this.

Source: Configuring Git to Handle Line Endings


Thank you for a simple, cross-platform, clear way to FIX it, rather than a huge discussion about the config meaning.
if git reset --hard is it possible my local change will be lost ? i just follow all comment metion above
Yes your local changes will be lost. The --hard parameter resets the index and the working tree so any changes to tracked files will be discarded. git-scm.com/docs/git-reset
What is meaning of git rm --cached -r .? Why git reset --hard isn't enough?
@gavenkoa @max You need the git rm --cached -r . If you do git reset --hard after changing the core.autocrlf setting, it will not re-convert the line endings. You need to clean the git index.
S
Sahil Mittal
git config core.autocrlf false

make sure to run this inside repository root
I don't understand how this can be useful. Half the people require autocrlf to be true for it to work, the other half need it to be false/input. So, what, are they supposed to randomly throw these one-off answers onto their console wall until something sticks and sorta "works" ? This is not productive.
I get an error "fatal: not in a git directory". I tried to cd to C:\Program Files\Git and C:\Program Files\Git\bin
@mbb setting autcrlf to false just punts the issue to every user of your project.
@pixelwiz : this command is setting the property only for the project (so you need to be under a git repository to run it). If you want to set this globally, use git config --global core.autocrlf false instead.
P
Peter Mortensen

Both unix2dos and dos2unix is available on Windows with Git Bash. You can use the following command to perform UNIX (LF) → DOS (CRLF) conversion. Hence, you will not get the warning.

unix2dos filename

or

dos2unix -D filename

But, don't run this command on any existing CRLF file, because then you will get empty newlines every second line.

dos2unix -D filename will not work with every operating system. Please check this link for compatibility.

If for some reason you need to force the command then use --force. If it says invalid then use -f.


Here's what the help option says: ` --u2d, -D perform UNIX -> DOS conversion`
@LarryBattle u2d and d2u is not the same thing I believe.
@Rifat I'm confused. Your comment says that dos2unix -D will convert windows line endings to linux line endings. Isn't that the same as DOS(CRLF) -> UNIX(LF) conversion. However dos2unix -h states that -D will perform UNIX(LF) -> DOS(CRLF) conversion. dos2unix More info: gopherproxy.meulie.net/sdf.org/0/users/pmyshkin/dos2unix
@LarryBattle Yes, you are right about -D. Actually, I posted the answer when I was a windows user. And, I made the comment more than a year later when I'm a mac user :D BTW, Thanks for the clarification.
This worked for me. I'm using Cygwin, which doesn't seem to support the -D switch - but there is the "unix2dos" command, which does the same thing. I wish I knew what caused the problem though - I have core.autocrlf = false and it's a Windows-only repository.
P
Peter Mortensen

A GitHub article on line endings is commonly mentioned when talking about this topic.

My personal experience with using the often recommended core.autocrlf configuration setting was very mixed.

I'm using Windows with Cygwin, dealing with both Windows and Unix projects at different times. Even my Windows projects sometimes use Bash shell scripts, which require Unix (LF) line endings.

Using GitHub's recommended core.autocrlf setting for Windows, if I check out a Unix project (which does work perfectly on Cygwin - or maybe I'm contributing to a project that I use on my Linux server), the text files are checked out with Windows (CRLF) line endings, creating problems.

Basically, for a mixed environment like I have, setting the global core.autocrlf to any of the options will not work well in some cases. This option might be set on a local (repository) Git configuration, but even that wouldn't be good enough for a project that contains both Windows- and Unix-related stuff (e.g., I have a Windows project with some Bash utility scripts).

The best choice I've found is to create per-repository .gitattributes files. The GitHub article mentions it.

Example from that article:

# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto

# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.c text
*.h text

# Declare files that will always have CRLF line endings on checkout.
*.sln text eol=crlf

# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary

In one of my project's repository:

* text=auto

*.txt         text eol=lf
*.xml         text eol=lf
*.json        text eol=lf
*.properties  text eol=lf
*.conf        text eol=lf

*.awk  text eol=lf
*.sed  text eol=lf
*.sh   text eol=lf

*.png  binary
*.jpg  binary

*.p12  binary

It's a bit more things to set up, but do it once per project, and any contributor on any OS should have no troubles with line endings when working with this project.


Running into this now, trying to manage a repo with Cygwin scripts among other basic text files. How would you handle files with no extension (e.g. "fstab", "sshd_config")? The linked article doesn't cover that scenario.
@MikeLoux Try this method: stackoverflow.com/a/44806034/4377192
I found that text=false eol=false worked somewhat similarly to binary. Does that sound right? It might be useful to indicate "I know these are text files, but I don't want them to be normalised"
P
Peter Mortensen

I think Basiloungas's answer is close, but out of date (at least on Mac).

Open the ~/.gitconfig file and set safecrlf to false:

[core]
       autocrlf = input
       safecrlf = false

That *will make it ignore the end of line char apparently (it worked for me, anyway).


It should be safecrlf (with an 'f')
P
Peter Mortensen

In Vim, open the file (e.g.: :e YOURFILEENTER), then

:set noendofline binary
:wq

Simply editing with vim would leave all line ending intact.
I've been having this problem with some Cocoapods files. The above fixed most of them; for the rest, s/{control-v}{control-m}// did the trick. The two control codes together make the ^M that those of us on OS X often see in Windows files.
T
Tim Abell

I had this problem too.

SVN doesn't do any line ending conversion, so files are committed with CRLF line endings intact. If you then use git-svn to put the project into git then the CRLF endings persist across into the git repository, which is not the state git expects to find itself in - the default being to only have unix/linux (LF) line endings checked in.

When you then check out the files on windows, the autocrlf conversion leaves the files intact (as they already have the correct endings for the current platform), however the process that decides whether there is a difference with the checked in files performs the reverse conversion before comparing, resulting in comparing what it thinks is an LF in the checked out file with an unexpected CRLF in the repository.

As far as I can see your choices are:

Re-import your code into a new git repository without using git-svn, this will mean line endings are converted in the intial git commit --all Set autocrlf to false, and ignore the fact that the line endings are not in git's preferred style Check out your files with autocrlf off, fix all the line endings, check everything back in, and turn it back on again. Rewrite your repository's history so that the original commit no longer contains the CRLF that git wasn't expecting. (The usual caveats about history rewriting apply)

Footnote: if you choose option #2 then my experience is that some of the ancillary tools (rebase, patch etc) do not cope with CRLF files and you will end up sooner or later with files with a mix of CRLF and LF (inconsistent line endings). I know of no way of getting the best of both.


I think there's a 4th option to add to your list, assuming one can afford to rewrite history: You can take a git repo that you initially created with git-svn, and rewrite its history to no longer have CRLF linefeeds. This would give you normalized linefeeds extending backwards through your whole svn history. User keo presents one solution at stackoverflow.com/a/1060828/64257.
About your footnote: rebase has no problem with CRLF. The only problem I know of is that the standard git merge tool will insert its conflict markers ("<<<<<<", ">>>>>>" etc.) with LF only, so a file with conflict markers will have mixed line endings. However, once you remove the markers, everything is fine.
It's possible git's handling has changed in the last 3 years, this was my direct experience with it at the time, I haven't had need to revisit this particular issue since. ymmv.
@sleske starting git 2.8, the merge markers will no longer introduce mixed line ending. See stackoverflow.com/a/35474954/6309
@VonC: That's cool. Good to know for the times I need to work on Windows.
P
Peter Mortensen

Removing the below from the ~/.gitattributes file,

* text=auto

will prevent Git from checking line-endings in the first place.


Incorrect. That line, if present, will override the configuration of core.autocrlf. If that is set to 'true', then no, removing that line won't prevent git from checking line endings.
Nonetheless, if core.autocrlf is set to false, if this one is not removed setting the autocrlf to false won't help much, so this one helped me (but is on its own not enough).
Upvoting this!! While the "will prevent git from checking" part isn't technically correct, this is the ONLY answer that specifically mentions the text= setting in .gitattributes at all (which, if present, WILL be a blocker). So the other answers are incomplete. I was going nuts trying figure out why my files continued to show up as "modified" no matter how many times I changed my autocrlf and safecrlf settings & checked out & cleared the git cache & hard reset.
P
Peter Mortensen

Most of the tools in Windows also accepts a simple LF in text files. For example, you can control the behaviour for Visual Studio in a file named '.editorconfig' with following example content (part):

 indent_style = space
 indent_size = 2
 end_of_line = lf    <<====
 charset = utf-8

Only the original Windows Notepad does not work with LF, but there are some more proper simple editor tools available!

Hence you should use LF in text files in Windows too. This is my message, and it is strongly recommended! There isn’t any reason to use CRLF in windows!

(The same discussion is using \ in include paths in C/++. It is bovine fecal matter. Use #include <pathTo/myheader.h> with slash!, It is the C/++ standard and all Microsoft compilers support it).

Hence the proper setting for Git is:

git config core.autocrlf false

My message: Forget such old thinking programs as dos2unix and unix2dos. Clarify in your team that LF is proper to use under Windows.


P
Peter Mortensen

How to make Git ignore different line endings

http://www.rtuin.nl/2013/02/how-to-make-git-ignore-different-line-endings/ (Not working)

You can disable the CRLF behaviour completely, or per filetype by changing entries in your .gitattributes file. In my case, I put this: -crlf This tells Git to ignore the line endings for all files. And does not change the files in your working directory. Even if you have the core.autocrlf set to true, false, or input.

echo "* -crlf" > .gitattributes

Do this on a separate commit or Git might still see whole files as modified when you make a single change (depending on if you have changed the autocrlf option).

This one really works. Git will respect the line endings in mixed line ending projects and not warn you about them.


This is especially useful when you want to convert between CRLF and LF, but you have a few .sh files that must stay intact. I use *.sh -crlf all the time...
Best solution. Combined with git rm --cached -r . and git reset --hard it works for everybody in the project.
The second link is broken: "500 Internal Server Error"
Hi @PeterMortensen, regarding your edits, as git is command line program that has it's origins in case sensitive environments, wouldn't it make sense to refer to it as 'git' instead of 'Git'?
P
Peter Mortensen

I don't know much about Git on Windows, but...

It appears to me that Git is converting the return format to match that of the running platform (Windows). CRLF is the default return format on Windows, while LF is the default return format for most other OSes.

Chances are, the return format will be adjusted properly when the code is moved to another system. I also reckon Git is smart enough to keep binary files intact rather than trying to convert LFs to CRLFs in, say, JPEG files.

In summary, you probably don't need to fret too much over this conversion. However, if you go to archive your project as a tarball, fellow coders would probably appreciate having LF line terminators rather than CRLF. Depending on how much you care (and depending on you not using Notepad), you might want to set Git to use LF returns if you can :)

Appendix: CR is ASCII code 13, LF is ASCII code 10. Thus, CRLF is two bytes, while LF is one.


Since no one seems to have said it, CR stands for "Carriage Return" and LF stands for "Line Feed". As a second note, many windows editors will silently change a text file with the LF character denoting a newline to instead be the pair of characters CRLF. The user of the editor won't even be warned, but Git will see the change.
P
Peter Mortensen

It should read:

warning: (If you check it out/or clone to another folder with your current core.autocrlf being true,)LF will be replaced by CRLF The file will have its original line endings in your (current) working directory.

This picture should explain what it means.

https://i.stack.imgur.com/ZXee5.jpg


It also means that what is sent up to Subversion (if you do that) will have the conversion.
P
Peter Mortensen

Make sure that you have installed the latest version of Git

I did as in a previous answer, git config core.autocrlf false, when using Git (version 2.7.1), but it did not work.

Then it works now when upgrading git (from 2.7.1 to 2.20.1).


I think you meant you had git 2.17.1. I was having the same issue and did the update and this fixed it as well. Glad I saw your answer!
P
Peter Mortensen

Open the file in Notepad++. Go to menu Edit → EOL Conversion. Click on the Windows Format. Save the file.


Also try using git config --global core.autocrlf false to prevent Git from setting the line endings to Unix on a commit. Follow up with git config core.autocrlf to check it is indeed set to false.
P
Peter Mortensen

The OP's question is Windows-related and I could not use others without going to the directory or even running file in Notepad++ as administrator did not work...

So had to go this route:

cd "C:\Program Files (x86)\Git\etc"
git config --global core.autocrlf false

P
Peter Mortensen

CRLF could cause some problem while using your "code" in two different OSes (Linux and Windows).

My Python script was written in a Linux Docker container and then pushed using Windows' Git Bash. It gave me the warning that LF will be replaced by CRLF. I didn't give it much thought, but then when I started the script later, it said:

/usr/bin/env: 'python\r': No such file or directory

Now that is an \r for ramification for you. Windows uses "CR" - carriage return - on top of '\n' as new line character - \n\r. That's something you might have to consider.


This should be emphasized more! It is common for a windows developer to use docker and bring up linux containers -- and if you bring a shell script in with git and it converts the LF to CRLF, it will break.
P
Peter Mortensen

Many text editors allow you to change to LF. See the Atom instructions below. It is simple and explicit.

Click CRLF on the bottom right:

https://i.stack.imgur.com/4qwaQm.png

Select LF in dropdown on top:

https://i.stack.imgur.com/l9b9Ll.png


P
Peter Mortensen

I just had the same error. It happened after installing NVM NVM on Windows 10.

Setting the autoclrf in all levels did not worked.

In CMD I used: “git ls-files --eol”

i/lf    w/crlf  attr/             src/components/quotes/ExQuoteForm.js
i/lf    w/lf    attr/             src/components/quotes/HighlightedQuote.js

Conclusion:

Files I made have the different ending.

To change the files and reset, do

git config core.autocrlf false
git rm --cached -r .
git reset --hard

Although:

In some projects I needed to delete the repository and start it fresh.


P
Peter Mortensen

In a GNU/Linux shell prompt, the dos2unix and unix2dos commands allow you to easily convert/format your files coming from MS Windows.


They are not installed by default in some versions of Ubuntu (and possibly many other Linux distributions).
P
Peter Mortensen

Other answers are fantastic for the general concept. I ran into a problem where after updating the warning still happened on existing repositories which had commits in previous setting.

Adding with --renormalize helped, e.g.,

git add --renormalize .

From the documentation:

" Apply the "clean" process freshly to all tracked files to forcibly add them again to the index. This is useful after changing core.autocrlf configuration or the text attribute in order to correct files added with wrong CRLF/LF line endings. This option implies -u."


True it has been changed. This commands works for me as well.
N
Navin Singh rangar

CR and LF are a special set of characters that helps format our code.

CR (/r) puts the cursor at the beginning of a line but doesn't create a new line. This is how macOS works.

LF (/n) creates a new line, but it doesn't put the cursor at the beginning of that line. The cursor stays back at the end of the last line. This is how Unix and Linux work.

CRLF (/r/f) creates a new line as well as puts the cursor at the beginning of the new line. This is how we see it in Windows OS.

To summarize:

LF (LINE FEED)

stands for Line Feed

denoted with /n

creates a new line in the code

The ASCII code is 10.

Used by Unix and other OSes based around it.

CR (CARRIAGE RETURN)

stands for CARRIAGE RETURN

denoted with /r

puts the cursor on the beginning of a line.

The ASCII code is 13.

Used by macOS and its predecessors.

CRLF (CARRIAGE RETURN AND LINE FEED)

stands for CARRIAGE RETURN and LINE FEED

denoted with /n/r

creates a new line and puts the cursor at the beginning of that new line.

The ASCII code is 10 for LF and 13 for CR.

Primarily used on Windows OS.

Git uses LF by default. So when we use Git on Windows, it throws a warning like- "CRLF will be replaced by LF" and automatically converts all CRLF into LF, so that code becomes compatible.

NB: Don't worry...see this less as a warning and more as a notification message.


What do you mean by "puts the cursnew line beginning" (seems incomprehensible)? Please respond by editing (changing) your answer, not here in comments (without "Edit:", "Update:", or similar - the answer should appear as if it was written today).
P
Peter Mortensen

I had the same issue, and doing git add . && git reset reverted all line endings correctly.