3

I'm working on a repo in Windows. The repo was originally created on a mac and all files in it use LF only for line endings. When I clone the repo on another mac I see that all files have LF as the line ending. When I clone on Windows, some files, but not all, have the line endings as CRLF. core.autocrlf is set to false. There are no attributes on the files as checked with git check-attr -a foo. If I run:

git rev-parse HEAD:foo   # Outputs "abc123...abc"
git cat-file -p "abc123...abc" | xxd

Then I see the file with LF endings. (I installed xxd on windows to try and minimize tooling that could be introducing errors after discovering that git cat-file -p ... > temp.txt was changing the encoding to UTF-16)

git status shows that there are no changes to foo. If I convert the line endings in foo from CRLF to just LF, then git status shows that there are changes. Even though the file should only ever have had LF.

If I drop into WSL on Windows and run git status then it shows all the files with the errant CRs in them as being changed. "Git Bash" gives the same results as Windows however.

What on earth is going on? How do I make git stop changing my line endings?

Dale Myers
  • 2,703
  • 3
  • 26
  • 48
  • Can you run this command : `git config --list --show-origin` in all the environments to see if there is any difference ? – Philippe Jun 23 '23 at 23:21
  • @Philippe Practically identical. There are some differences in things like the Windows one having some SourceTree specific entries and a global gitignore file (which contains `._DS_Store` only). – Dale Myers Jun 26 '23 at 18:13
  • side note: Git commands resolve revision expressions to id's early. `git cat-file -p HEAD:foo` will do. – jthill Jun 26 '23 at 19:25
  • I ran into a problem on a CentOS 7 server which was using git 1.8.3.1 seven years after git 2 was released! You can use `git ls-files --eol` to check line endings. Useful information [here](https://www.aleksandrhovhannisyan.com/blog/crlf-vs-lf-normalizing-line-endings-in-git/#verifying-line-endings-in-git-for-any-file) – Zaq Jun 27 '23 at 01:07
  • @Zaq I mentioned `git ls-files --eol` in [March 2016](https://stackoverflow.com/a/35204436/6309): that would be for Git 2.8+, not Git 1.8. That can help here though. – VonC Jun 27 '23 at 08:57
  • @VonC, yes... I was surprised at how old that git was. It was actually in a BitBucket Pipeline using `atlassian/default-image:latest`! There's no point trying to get git to help if it's too old... Worth checking. – Zaq Jun 28 '23 at 00:48

3 Answers3

2

What does it do if it isn't set? If you can add this as a dedicated answer

That is what is explained in "How line ending conversions work with git core.autocrlf between different operating systems"

It confirms that the default value for core.autocrlf is true on Windows.

╔═══════════════╦══════════════╦══════════════╦══════════════╗
║ core.autocrlf ║     false    ║     input    ║     true     ║
╠═══════════════╬══════════════╬══════════════╬══════════════╣
║               ║ LF   => LF   ║ LF   => LF   ║ LF   => CRLF ║
║ git checkout  ║ CR   => CR   ║ CR   => CR   ║ CR   => CR   ║
║               ║ CRLF => CRLF ║ CRLF => CRLF ║ CRLF => CRLF ║
╠═══════════════╬══════════════╬══════════════╬══════════════╣
║               ║ LF   => LF   ║ LF   => LF   ║ LF   => LF   ║
║ git commit    ║ CR   => CR   ║ CR   => CR   ║ CR   => CR   ║
║               ║ CRLF => CRLF ║ CRLF => LF   ║ CRLF => LF   ║
╚═══════════════╩══════════════╩══════════════╩══════════════╝
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
0

First, double-check, from your repository local root folder, that your setting is set to "false":

git config --show-origin --get core.autocrlf

(When using Windows Subsystem for Linux (WSL), it is important to note that WSL has its own Git configuration separate from Windows. Ensure the configuration within WSL also has core.autocrlf set to false.)

Check also if there's a .gitattributes file in the repository. This file can override core.autocrlf settings. If it exists, look for any line that might be affecting line endings, like:

* text=auto

If such a line exists, it could be causing Git to automatically convert line endings. You might want to change it to:

* text=false

Or remove it altogether.

And run git add --renormalize . to apply the new directives.

Make sure the settings of your editor is not converting line endings on save.

Make also sure the .git/hooks directory does not include any pre-commit or post-checkout hooks that might be altering line endings.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • `git config --show-origin --get core.autocrlf` didn't show anything. There's no `.gitattributes`, and there's nothing in the hooks folder. – Dale Myers Jun 27 '23 at 08:48
  • @DaleMyers So first things first: `git config --global core.autocrlf false`. Then try and clone your repository again. – VonC Jun 27 '23 at 08:56
  • So I set this and cloned again and sure enough, the line endings were correct. However, `core.autocrlf` simply wasn't set before and it _should_ default to false as far as I understand. Either way, it certainly shouldn't just pick a random subset of files to make the changes on. – Dale Myers Jun 27 '23 at 10:29
  • 1
    @DaleMyers No, I have spent years stating that it did not default to false: [2009](https://stackoverflow.com/a/1250133/6309), [2010](https://stackoverflow.com/a/2825829/6309), [2017](https://stackoverflow.com/a/44224929/6309), ... – VonC Jun 27 '23 at 10:53
  • I guess the mystery is what _does_ it do if it isn't set? If you can add this as a dedicated answer I'll accept it. – Dale Myers Jun 27 '23 at 11:40
  • @DaleMyers I have posted a [dedicated answer](https://stackoverflow.com/a/76564664/6309). Don't pay attention to the downvote to this answer: I just got serial downvoted for some reason. – VonC Jun 27 '23 at 12:03
0

As a diagnostic step that wouldn't fit as a comment, plus some comments to provide context for the step:

I'll be surprised if powershell isn't what's behind the unwanted UTF-16 conversion. The line endings act more like some sneaky attribute (but I see you did git check-attr -a so looking like not that) or filter processing.

Try running without any site overrides. Go in to your troubled clone and (I'm using bash, convert as needed but never let powershell touch any data you don't want it rewriting as it sees fit)

git clone --template= -ns . `mktemp -d`    # or `../deleteme` if you don't have mktemp
cd $_
git config core.autocrlf false
git config --system -l    # ok if this errors out
git config --get-regexp core
git checkout

Then check whethergit grep -l $'\r' lists files that git grep -l $'\r' @ doesn't. For a sample of any that do, comment with or edit into your question the git check-attr -a $thatfile results for that file, or if none do say that, and we'll do another round.

jthill
  • 55,082
  • 5
  • 77
  • 137
  • I ran through this and the carriage returns are still there. `git config --system -l` did error as you said. It said `fatal: unable to read config file 'C:/Program Files/Git/etc/gitconfig': No such file or directory` which isn't surprising as I deleted it as one of my first debugging steps to try and reduce possible config areas. – Dale Myers Jun 27 '23 at 09:08
  • So, the two `git grep`s produced different lists? – jthill Jun 27 '23 at 14:50