167

I am trying to get git to not change any line endings whatsoever for any operation. Unfortunately, it seems to do so not matter what. I have reduced it down to the following test case, which has as many different mechanisms for disabling this behavior as I could find.


  • Begin with two machines (Windows computer = A, Linux computer = B)
  • On both machines: git config --global core.autocrlf false
  • On both machines: git config --global core.eol crlf (just in case)

  • Make new repository on A. From an empty folder:
    • git init --shared (then unhide the created .git directory)
    • Make a new file .gitignore in the repository
    • Make a new file .gitattributes in the repository with the single line: * -text
    • git add ., then git commit -m "initial commit" to work around, e.g. this.
    • git branch master_recv
    • Add remotes
  • Make a new file document.txt in the repository containing CRLF
  • Commit: git add -A, then git commit -m "<something>"
  • Note that A's document.txt still contains CRLF (and deleting it and resetting with --hard returns the version still with CRLF)

  • SCP the whole directory to computer B
  • Add a new file new file containing CRLF
  • Commit: git add -A, then git commit -m "<something>"
  • Note that B's document.txt and B's new file both still contain CRLF

  • Pull B's master to A: git pull <remote> master:master_recv
  • A's document.txt has changed to LF. The added file new file also contains LF.

The problem does not occur if B is a Windows machine.

Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
geometrian
  • 14,775
  • 10
  • 56
  • 132
  • Has `core.autocrlf` *always* been false? It sounds like you have `\n` line endings in your repository already? There is *no* setting to change `\n` in your repository to `\r\n` in your working directory. – Edward Thomson Feb 18 '14 at 00:14
  • 1
    It has not always been set (for example when the repo was created originally). However, there shouldn't be any CR line endings in the repo already. Also, again, I don't _want_ any changes to happen whatsoever. – geometrian Feb 18 '14 at 01:48
  • I ask because your setup *should* preserve your line endings as CRLF. Could you post some file in your repository *with* its object ID just for my (admittedly probably annoying) edification? – Edward Thomson Feb 18 '14 at 02:11
  • @EdwardThomson how do you mean? The repo isn't public (since the Linux machine isn't). I'll assume you want an example file. See edit. – geometrian Feb 18 '14 at 03:23
  • Yep, I agree that that file has CRLF line endings. Can you clarify one thing: you mentioned that the "windows machine's newlines change to CR!" Surely that was a typo, or are you really getting Mac OS 9-style carriage return line endings? – Edward Thomson Feb 18 '14 at 04:29
  • It was a typo; fixed. Note also, on the Linux machine, the file seems to stay CRLF (although I don't do a checkout there, only a change and commit before the subsequent pull). – geometrian Feb 18 '14 at 04:35
  • So, I appreciate the edit for clarification, but it still doesn't elucidate the problem. Did you `git add document.txt` on the Linux machine? Did you really `git pull` on the Windows machine or did you SCP the working directory back over to it? – Edward Thomson Feb 18 '14 at 18:04
  • @EdwardThomson see edit. Also, chatp? – geometrian Feb 19 '14 at 02:03

6 Answers6

100

One simple solution is:

  • make sure core.autocrlf is set to false for all repos:
    git config --global core.autocrlf false

If there are conversions automatically done, that mean a .gitattributes core.eol directive is there within the repo.

With Git 2.8+ (March 2016), check if there are still eol transformation with:

git ls-files --eol
Yam Marcovic
  • 7,953
  • 1
  • 28
  • 38
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 3
    As above, I had tried this (although not with the global flag), and it didn't work. git version is `1.8.5.2`. – geometrian Feb 17 '14 at 16:45
  • @IanMallett "At this point, it appears that the Linux machine still has CRLF": it will until you re-normalize its content, or clone it (like you did on windows) – VonC Feb 18 '14 at 06:29
  • 1
    If you're trying to make this for only one repo then simply run `git config core.autocrlf false` -- mentioning this because generally autocrlf should be `true` for windows and `input` for others, but sometimes you need something specific for weird edge cases. In my case, I've downloaded some files and want to record changes I make so I can remember what I did (as opposed to tracking changes to code). I don't know if the line endings are important (and want diffs to make sense against the "real" stuff") so I disabled autocrlf. – Captain Man Aug 31 '20 at 20:31
  • The `core.autocrlf=false` does not mean the conversation on checkout is not performed. It is dependent on the `.gitattributes` in the end point directory being checkouted. – Andry Mar 28 '23 at 09:49
  • @Andry I agree. I believe that is what I mean with the part of the answer which says: "If there are conversions automatically done, that mean a `.gitattributes` `core.eol` directive is there within the repo.". – VonC Mar 28 '23 at 18:12
  • @VonC Do you known how to completely disable crlf conversion on checkout irrespective to `.gitattributes`? – Andry Mar 28 '23 at 23:57
  • @Andry I do not think so: you would need to edit/modify the `.gitattributes` file itself. See [this answer](https://stackoverflow.com/a/75034412/6309) and others on that page to show illustrations around that challenge. – VonC Mar 29 '23 at 08:41
94

Inside your project, there should be a .gitattributes file. Most of the time, it should look like below (or this screen-shot):

# Handle line endings automatically for files detected as text 
# and leave all files detected as binary untouched.
* text=auto

# Never modify line endings of our bash scripts
*.sh -crlf

#
# The above will handle all files NOT found below
#
# These files are text and should be normalized (Convert crlf => lf)
*.css           text
*.html          text
*.java          text
*.js            text
*.json          text
*.properties    text
*.txt           text
*.xml           text

# These files are binary and should be left untouched
# (binary is macro for -text -diff)
*.class         binary
*.jar           binary
*.gif           binary
*.jpg           binary
*.png           binary

Change * text=auto to * text=false to disable automatic handling (see screen-shot).

Like this:

enter image description here

If your project doesn't have a .gitattributes file, then the line endings are set by your git configurations. To change your git configurations, do this:

Go to the config file in this directory:

  1. C:\ProgramData\Git\config

  2. Open up the config file in Notepad++ (or whatever text editor you prefer)

  3. Change "autocrlf=" to false.

enter image description here

For users of TortoiseGIT: the Auto CrLf convert settings are on the GUI, in section GIT.

Traveler
  • 213
  • 3
  • 10
Gene
  • 10,819
  • 1
  • 66
  • 58
  • 54
    Why use pictures instead of code tags? Very inconvenient – Clint Oct 16 '17 at 18:43
  • 61
    Because I can add a big red box in the picture to highlight stuff. – Gene Mar 04 '18 at 18:56
  • 38
    Using `* text=false` does not unset text: it leaves text set to the string value false. This has the same effect as leaving text unspecified (not specifically unset). Using `* -text` gives it the special unset setting. Unsetting the text attribute on a path tells git not to attempt any end-of-line conversion upon checkin or checkout. – JustAMartin Mar 08 '18 at 14:01
  • Thank you @Gene for this answer. This has been driving me crazy all day, and this one solved it for me! – LeopardSkinPillBoxHat May 31 '18 at 00:33
  • No problem. Glad I can help. – Gene May 31 '18 at 15:21
  • @Gene, you also could just use code tags and only show the relevant code. The additional context is not useful in any of these examples, there would then not be any need for big red boxes. – Michael Leonard Nov 07 '18 at 18:39
  • 15
    Sorry to say that I can't say thanks for this answer. Cost me half a day to find out that someone had followed the misleading advice. As @JustAMartin pointed out `* text=false` has not effect. Please fix the answer! – Paul B. Nov 23 '18 at 11:18
  • @Gene comments can help you highlight and point out much better whatever solution you need to show, inside a code tag – Salvioner Jun 26 '19 at 14:40
  • 1
    Including a .gitattributes file in my project and only adding the `*.sh -crlf` fixed the issue for me. Setting `* text=false` requires you to set up your line ending conversion manually for every kind of file it seems. According to [the git docs](https://git-scm.com/docs/gitattributes#_effects) that is – Rodin10 Sep 04 '19 at 12:14
  • To prevent converting CRLF to LF on my Ubuntu: in project dir: nano .gitattributes `*.java -text` in /etc/ nano gitattributes `* -text autolf=false` Thank you! – Trayan Momkov Jun 08 '20 at 19:15
  • 4
    This answer is **not** correct. As noted by @JustAMartin below and in the above comment section, you must use `* -text` and **not** `* text=false`. Until this answer is fixed, I have down voted it. Please fix this answer. – Code Doggo Dec 08 '20 at 22:01
  • 1
    It worked 3 years ago when I posted it. Things most likely changed. I'm going to keep the code I know works when I tried it. Thanks for letting others know that code might have changed since the attempt 3 years go. – Gene Dec 09 '20 at 01:32
  • 2
    Leaving code that doesn't work up because it used to be correct is knowingly misleading readers – Neowizard Oct 31 '21 at 16:24
  • That all depends on the software stack you're running and the version numbers. – Gene Nov 02 '21 at 22:23
  • @JustAMartin @CodeDoggo Before reading these comments I discovered `* text=auto` didn't work and adapted the answer to `* -crlf`, which does seem to work. But what is the difference between the `* -text` you're recommending, and `* -crlf` ? – jez Dec 09 '21 at 21:28
  • https://docs.github.com/en/get-started/getting-started-with-git/configuring-git-to-handle-line-endings – Gene Dec 11 '21 at 01:13
29

Here is how you do this for a single repo.

Create the file .gitattributes at the root of the repo with this line in it

* -text

That's it. This is a wildcard matching all files, telling git to unset the text attribute. This means git treats all files as non-text when doing line-ending-normalization, disabling it completely. Other text-specific git commands are unaffected. Only line ending normalization is changed.

Max
  • 21,123
  • 5
  • 49
  • 71
  • This also means all line diffing logic in git is lost. How do you perform a merge in this setup? – Matias Grioni Aug 23 '22 at 05:08
  • @MatiasGrioni I'm not sure what you mean. I just tested this out and git's mergetool still opened my normal text diff tool when I had a merge conflict – Max Aug 23 '22 at 12:12
  • Yes, I think I'm confused as to how git handles binary files. It seems like it may just make a difference in some "surface level" commands but the behavior can be overridden with the right flags. – Matias Grioni Aug 23 '22 at 16:46
  • 2
    @MatiasGrioni in the [gitattributes docs](https://git-scm.com/docs/gitattributes) it explains that the `text` attribute is _only_ for line ending normalization. So unsetting it will only affect that aspect of git. All other text handling aspects should still be fine – Max Aug 24 '22 at 12:36
14

I figured it out. It seems that the SCP program was converting the line endings. I noticed this when I tried deliberately making a file with LF endings and then observing that it appeared as CRLF when downloaded.

Since this was the solution for me, I'm accepting this answer, but people of the future should also refer to the other answers for a more general solution.

geometrian
  • 14,775
  • 10
  • 56
  • 132
6

From gitattributes(5) Manual Page "Effects" topic

text

This attribute enables and controls end-of-line normalization. When a text file is normalized, its line endings are converted to LF in the repository. To control what line ending style is used in the working directory, use the eol attribute for a single file and the core.eol configuration variable for all text files.

Set

Setting the text attribute on a path enables end-of-line normalization and marks the path as a text file. End-of-line conversion takes place without guessing the content type.

Unset Unsetting the text attribute on a path tells Git not to attempt any end-of-line conversion upon checkin or checkout.

core.autocrlf in new (1.7.2+) Git not used, core.eol and correct setting|unsetting of text-attribute considered as more reliable way

Lazy Badger
  • 94,711
  • 9
  • 78
  • 110
  • 1
    In the `.gitattributes` file, I had explicitly disabled everything as text though, right? Also, I don't see it with an option to make it not do conversion (although `crlf` might have no effect)? – geometrian Feb 17 '14 at 16:49
  • 13
    Important thing that gets often confused - to unset `text` and prevent any conversion, you should set .gitattributes to `* -text` and not to `* text=false`. `false` is not a valid value for `text` attribute - git won't recognize it and will fall back to its default autocrlf setting instead. Also, after changing `text` value you have to backup all files from your local repo, do a commit, then restore the files with correct end-of-lines as you need them, and commit them back. Then your end-of-lines won't be modified by git ever again. – JustAMartin Jun 28 '19 at 12:06
1

I was trying to keep files from switching to CRLF line ending on Windows and found that adding a .gitattributes file to the repository with *.md eol=lf kept my README.md file as LF line ending when I cloned the repo from GitHub.

I had no luck with the git config core.autocrlf false setting or setting my VSCode editor to use LF line endings.

w. Patrick Gale
  • 1,643
  • 13
  • 22