threads / discuss / 63782

Why doesn't git core.eol=lf work?

Subject: Why doesn't git core.eol=lf work?

## tl;dr

7 messages between Jul 12, 2025 and Jul 13, 2025.

replies: 6people: 4as markdown or json

Jason Cho· Jul 12, 2025, 09:45 UTC · lore
```MINGW64 /tmp/summer-temp/dbeaver/docs ((e4219ccb38...))
$ git log -1 --patch license_header.txt
commit b5121d4a6e8f3f21079920180b0fb14ada6d3349
Author: serge-rider <serge@jkiss.org>
Date:   Thu Jan 10 21:56:55 2019 +0300
    License header update (2019)
diff --git a/docs/license_header.txt b/docs/license_header.txt
index 86de505a18..d75b48e98e 100644
--- a/docs/license_header.txt
+++ b/docs/license_header.txt
@@ -1,5 +1,5 @@
    DBeaver - Universal Database Manager
-   Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
+   Copyright (C) 2010-2019 Serge Rider (serge@jkiss.org)^M

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.

MINGW64 /tmp/summer-temp/dbeaver/docs ((a3f59b66ed...))
$ git check-attr --all -- license_header.txt

MINGW64 /tmp/summer-temp/dbeaver/docs ((a3f59b66ed...))
$ rm license_header.txt

MINGW64 /tmp/summer-temp/dbeaver/docs ((a3f59b66ed...))
$ git -c core.autocrlf=false -c core.eol=lf checkout -f HEAD -- license_header.txt

MINGW64 /tmp/summer-temp/dbeaver/docs ((a3f59b66ed...))
$ cat -A license_header.txt
   DBeaver - Universal Database Manager^M$
   Copyright (C) 2010-2019 Serge Rider (serge@jkiss.org)^M$
^M$
   Licensed under the Apache License, Version 2.0 (the "License");^M$
   you may not use this file except in compliance with the License.^M$
   You may obtain a copy of the License at^M$

MINGW64 /tmp/summer-temp/dbeaver/docs ((a3f59b66ed...))
$ git --version
git version 2.47.0.windows.2
```

I ask git to force checkout license_header.txt with LF line ending, but `cat` tells me the file is checked out with CRLF. Why?
Torsten Bögershausen· Jul 12, 2025, 10:30 UTC · re: Jason Cho · lore

Re: Why doesn't git core.eol=lf work?

On Sat, Jul 12, 2025 at 09:45:39AM +0000, Jason Cho wrote:
Show 45 quoted lines
> ```MINGW64 /tmp/summer-temp/dbeaver/docs ((e4219ccb38...))
> $ git log -1 --patch license_header.txt
> commit b5121d4a6e8f3f21079920180b0fb14ada6d3349
> Author: serge-rider <serge@jkiss.org>
> Date:   Thu Jan 10 21:56:55 2019 +0300
> 
>     License header update (2019)
> 
> diff --git a/docs/license_header.txt b/docs/license_header.txt
> index 86de505a18..d75b48e98e 100644
> --- a/docs/license_header.txt
> +++ b/docs/license_header.txt
> @@ -1,5 +1,5 @@
>     DBeaver - Universal Database Manager
> -   Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
> +   Copyright (C) 2010-2019 Serge Rider (serge@jkiss.org)^M
> 
>     Licensed under the Apache License, Version 2.0 (the "License");
>     you may not use this file except in compliance with the License.
> 
> MINGW64 /tmp/summer-temp/dbeaver/docs ((a3f59b66ed...))
> $ git check-attr --all -- license_header.txt
> 
> MINGW64 /tmp/summer-temp/dbeaver/docs ((a3f59b66ed...))
> $ rm license_header.txt
> 
> MINGW64 /tmp/summer-temp/dbeaver/docs ((a3f59b66ed...))
> $ git -c core.autocrlf=false -c core.eol=lf checkout -f HEAD -- license_header.txt
> 
> MINGW64 /tmp/summer-temp/dbeaver/docs ((a3f59b66ed...))
> $ cat -A license_header.txt
>    DBeaver - Universal Database Manager^M$
>    Copyright (C) 2010-2019 Serge Rider (serge@jkiss.org)^M$
> ^M$
>    Licensed under the Apache License, Version 2.0 (the "License");^M$
>    you may not use this file except in compliance with the License.^M$
>    You may obtain a copy of the License at^M$
> 
> MINGW64 /tmp/summer-temp/dbeaver/docs ((a3f59b66ed...))
> $ git --version
> git version 2.47.0.windows.2
> ```
> 
> I ask git to force checkout license_header.txt with LF line ending, but `cat` tells me the file is checked out with CRLF. Why?
> 

Side note: Did you ? I would suspect that core.autocrlf=false switches off the CRLF handling. And this could be a command line: git -c core.autocrlf=input -c core.eol=lf checkout -f HEAD -- license_header.txt

But now to the real stuff: It may be that your file had been commited with LF or mixed CRLF into the repo. In this case will Git not change CRLF into LF at checkout. What does git ls-files --eol license_header.txt give you ?

Beside that, I would recommend to set up a .gitatrributes file and add it to the repo. echo "* text=auto" >.gitattributes git add --renormalize . git commit -m "Normalize line endings"

Jason Cho· Jul 12, 2025, 10:56 UTC · re: Torsten Bögershausen · lore

Re: Why doesn't git core.eol=lf work?

Show 6 quoted lines
> But now to the real stuff:
> It may be that your file had been commited with LF or mixed CRLF into the repo.
> In this case will Git not change CRLF into LF at checkout.
> What does
> git ls-files --eol license_header.txt
> give you ?

$ git ls-files --eol license_header.txt i/crlf w/crlf attr/ license_header.txt

 
Show 6 quoted lines
> Beside that, I would recommend to set up a .gitatrributes file
> and add it to the repo.
> echo "* text=auto" >.gitattributes
> 
> git add --renormalize .
> git commit -m "Normalize line endings"
I am building a tool to analyze codebases, such as which function is moved from one file to another. Different line endings fail string equality.
Admittedly I can make a local commit to normalize all files. But it's best if a simple config `core.eol` can work.
Johannes Sixt· Jul 12, 2025, 13:35 UTC · re: Jason Cho · lore

Re: Why doesn't git core.eol=lf work?

Am 12.07.25 um 11:45 schrieb Jason Cho:
Show 20 quoted lines
> ```MINGW64 /tmp/summer-temp/dbeaver/docs ((e4219ccb38...))
> $ git log -1 --patch license_header.txt
> commit b5121d4a6e8f3f21079920180b0fb14ada6d3349
> Author: serge-rider <serge@jkiss.org>
> Date:   Thu Jan 10 21:56:55 2019 +0300
> 
>     License header update (2019)
> 
> diff --git a/docs/license_header.txt b/docs/license_header.txt
> index 86de505a18..d75b48e98e 100644
> --- a/docs/license_header.txt
> +++ b/docs/license_header.txt
> @@ -1,5 +1,5 @@
>     DBeaver - Universal Database Manager
> -   Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
> +   Copyright (C) 2010-2019 Serge Rider (serge@jkiss.org)^M
> 
>     Licensed under the Apache License, Version 2.0 (the "License");
>     you may not use this file except in compliance with the License.
> 

Since you posted `git diff` output, may I ask if your concern is actually the ^M in the diff output, which you intend to fix with automatic CRLF-to-LF conversion?

In that case, the simpler solution is to set core.whitespace such that it includes 'cr-at-eol' to convince `git diff` not to mark the CR in the CRLF pair as a trailing whitespace error.

-- Hannes
Jason Cho· Jul 12, 2025, 19:15 UTC · re: Johannes Sixt · lore

Re: Why doesn't git core.eol=lf work?

Show 5 quoted lines
> 
> Since you posted `git diff` output, may I ask if your concern is
> actually the ^M in the diff output, which you intend to fix with
> automatic CRLF-to-LF conversion?
> 
No, my intent is to find moved or duplicated text among files. 
Let's say license_header.txt has 

DBeaver - Universal Database Manager^M Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)

and another.txt has

DBeaver - Universal Database Manager Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)

My tool doesn't think the two pieces of txt the same because of ^M.
Although my tool can do normalization internally, if git checks out files to CRLF due to core.autocrlf=true, my tool is fighting against git. git shouldn't spend time converting to CRLF which is about to be converted back to LF by my tool.
That's why I set core.autocrlf=false, and ask git to normalize files to LF.
So the problem is that, conversion to LF is not happening.
Lidong Yan· Jul 13, 2025, 07:43 UTC · re: Jason Cho · lore

Re: Why doesn't git core.eol=lf work?

Jason Cho <jason11choca@proton.me> write:
Show 26 quoted lines
> 
>> 
>> Since you posted `git diff` output, may I ask if your concern is
>> actually the ^M in the diff output, which you intend to fix with
>> automatic CRLF-to-LF conversion?
>> 
> 
> No, my intent is to find moved or duplicated text among files. 
> 
> Let's say license_header.txt has 
> 
> DBeaver - Universal Database Manager^M
> Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
> 
> and another.txt has
> 
> DBeaver - Universal Database Manager
> Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
> 
> My tool doesn't think the two pieces of txt the same because of ^M.
> 
> Although my tool can do normalization internally, if git checks out files to CRLF due to core.autocrlf=true, my tool is fighting against git. git shouldn't spend time converting to CRLF which is about to be converted back to LF by my tool.
> 
> That's why I set core.autocrlf=false, and ask git to normalize files to LF.
> 
> So the problem is that, conversion to LF is not happening.

I believe that it's impossible to check out CRLF from the index as LF. You have to use your tool to do that.

The definition of core.eol=lf is here:
  https://git-scm.com/docs/gitattributes/2.9.5#:~:text=Set,-to%20string%20value%20%22lf

This means that when you use git add to stage files, Git will convert CRLF line endings to LF. However, when you check out files, Git will leave the line endings unchanged.

Thanks, Lidong

Jason Cho· Jul 13, 2025, 14:08 UTC · re: Lidong Yan · lore

Re: Why doesn't git core.eol=lf work?

Show 12 quoted lines
> 
> 
> I believe that it's impossible to check out CRLF from the index as LF.
> You have to use your tool to do that.
> 
> The definition of core.eol=lf is here:
> https://git-scm.com/docs/gitattributes/2.9.5#:~:text=Set,-to string value "lf
> 
> This means that when you use git add to stage files, Git will convert
> CRLF line endings to LF. However, when you check out files, Git will
> leave the line endings unchanged.
> 
I see. Thank you so much. This detail was so subtle and it totally flew under my radar.

← back to recent threads