214

How do I make

git status

ignore line ending differences?

Background info:

I use randomly Windows and Linux to work on the project. The project is in Dropbox.

I found a lot about how do make git diff ignore line endings. Since i use meld git diff opens meld for each file. And meld says "identical file".

So how do I avoid this. Git should only open meld for changed files. And git status should not report files as changed if only the file ending is different.

EDIT: Cause:

This happened because of this setting on Windows

core.autocrlf true

So I checked out the working copy on Linux and set core.autocrlf false on Windows.

It would be still nice to know how to make git status ignore different new lines.

Thorsten Niehues
  • 13,712
  • 22
  • 78
  • 113
  • 4
    If you're sharing the file using dropbox on different platforms you're going to have this happen unless you explicitly tell git to treat all files as binary. The proper solution is **not to use dropbox** for git repositories – Anya Shenanigans Dec 10 '13 at 13:54
  • mind you: http://stackoverflow.com/questions/2825428/why-should-i-use-core-autocrlf-true-in-git - this may help somewhat – Anya Shenanigans Dec 10 '13 at 14:02
  • I found out how it works nice with Dropbox : by setting core.autocrlf false – Thorsten Niehues Dec 12 '13 at 15:01
  • 5
    AFAIK telling git to treat files as binary also has the side effect of changing the way it diffs the file. The proper solution is to tell git to ignore line endings. 2 of my least favourite things: dealing with line ending problems and unnecessary snarky FUD about the way people set their repos up :) – ChrisM Sep 22 '17 at 09:48
  • 2
    Wow, it took me a while that for this problem `core.autocrlf` is the root cause on Windows, but also a cure on Linux. The problem is, `autocrlf` is global on Windows, and the repo doesn't have that setting in `.git/config`. By running a local `git config core.autocrlf true` I got rid of spurious changes on my NTFS working copy cloned on Windows but accessed on Linux. (now there are only spurious changes with symlinks - NTFS symlinks DO WORK on fuseblk mounts, but Git sees them as modified...) – Tomasz Gandor Oct 15 '18 at 04:26

9 Answers9

197

Try setting core.autocrlf value like this :

git config --global core.autocrlf true
Saša Šijak
  • 8,717
  • 5
  • 47
  • 82
  • 7
    @ThorstenNiehues I use that setting on some work project. On work I must use windows, home I use mac and linux. Before this I had the same problem as you, after that setting everything was ok. – Saša Šijak Dec 12 '13 at 15:26
  • 1
    That's strange because a checkout on windows has \r\n line endings on Linux only \n Do you have both working-copies in Dropbox (or similar)? – Thorsten Niehues Dec 13 '13 at 07:49
  • 3
    @ThorstenNiehues No, git repository is on github. Hmm, maybe dropbox is somehow screwing with the line endings when it syncs files? It does seems strange to use dropbox for git. Try using bitbucket (it have free private repositories), just make one small repo and test on your 2 machines with some small text files. – Saša Šijak Dec 13 '13 at 09:11
  • 1
    1. The working copy and local repo is in Dropbox (I don't need a public repository) that's probably the difference – Thorsten Niehues Dec 13 '13 at 10:46
  • Maybe set `core.eol=lf` so that both sides are converting to `lf` and not to the defaults `native`? – Jan Katins Jun 01 '16 at 11:05
  • This fixed Bash Git and GitHub Desktop diffs for me on Windows while using WSL. – MattMS Jun 20 '18 at 05:53
  • 6
    In Windows: `core.autocrlf true` is a working setting in CygWin. `core.safecrlf false` is a working setting in git bash or mingw – jaques-sam Oct 17 '18 at 08:40
  • From https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration, "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." This means this answer doesn't ignore line ending differences but attempts to automatically correct them, which is different. In my use case (using both linux and windows on the same file via network mount drive) this is actually the cause of the problem - if I check out on windows git installation it adds CRLF; on linux, LF. – Tom Wyllie Jun 29 '20 at 01:00
  • This does not tell git to ignore line breaks – Luke Pring Feb 04 '21 at 11:40
  • 1
    Be careful when doing this because some Linux scripts might stop working – Diego Victor de Jesus Oct 08 '21 at 11:27
  • As mentioned by @DiegoVictordeJesus, the usage of `--global` can be dangerous, I would suggest the usage of `--local` instead. – Ilario Gelmetti Nov 02 '21 at 22:14
96

This answer seems relevant since the OP makes reference to a need for a multi-OS solution. This Github help article details available approaches for handling lines endings cross-OS. There are global and per-repo approaches to managing cross-os line endings.

Global approach

Configure Git line endings handling on Linux or OS X:

git config --global core.autocrlf input

Configure Git line endings handling on Windows:

git config --global core.autocrlf true

Per-repo approach:

In the root of your repo, create a .gitattributes file and define line ending settings for your project files, one line at a time in the following format: path_regex line-ending-settings where line-ending-settings is one of the following:

  • text
  • binary (files that Git should not modify line endings for - as this can cause some image types such as PNGs not to render in a browser)

The text value can be configured further to instruct Git on how to handle line endings for matching files:

  • text - Changes line endings to OS native line endings.
  • text eol=crlf - Converts line endings to CRLF on checkout.
  • text eol=lf - Converts line endings to LF on checkout.
  • text=auto - Sensible default that leaves line handle up to Git's discretion.

Here is the content of a sample .gitattributes file:

# Set the default behavior for all files.
* text=auto

# Normalized and converts to 
# native line endings on checkout.
*.c text
*.h text

# Convert to CRLF line endings on checkout.
*.sln text eol=crlf

# Convert to LF line endings on checkout.
*.sh text eol=lf

# Binary files.
*.png binary
*.jpg binary

More on how to refresh your repo after changing line endings settings here. Tldr:

backup your files with Git, delete every file in your repository (except the .git directory), and then restore the files all at once. Save your current files in Git, so that none of your work is lost.

git add . -u

git commit -m "Saving files before refreshing line endings"

Remove the index and force Git to rescan the working directory.

rm .git/index

Rewrite the Git index to pick up all the new line endings.

git reset

Show the rewritten, normalized files.

In some cases, this is all that needs to be done. Others may need to complete the following additional steps:

git status

Add all your changed files back, and prepare them for a commit. This is your chance to inspect which files, if any, were unchanged.

git add -u

It is perfectly safe to see a lot of messages here that read[s] "warning: CRLF will be replaced by LF in file."

Rewrite the .gitattributes file.

git add .gitattributes

Commit the changes to your repository.

git commit -m "Normalize all the line endings"

user4603841
  • 1,246
  • 9
  • 8
51

Use .gitattributes instead, with the following setting:

# Ignore all differences in line endings
*        -crlf

.gitattributes would be found in the same directory as your global .gitconfig. If .gitattributes doesn't exist, add it to that directory. After adding/changing .gitattributes you will have to do a hard reset of the repository in order to successfully apply the changes to existing files.

Trashman
  • 1,424
  • 18
  • 27
  • It worked for me in one stream, but when I tried to create it in another stream for the same project, it still shows Newline differences. – pfernandom Feb 25 '16 at 22:44
  • 1
    @pfernandom , do you possibly have multiple .gitattributes in your project? It will look at the most "local" version first, so if you have one in the local directory where the files are, it will use that one over your project wide one. – Trashman Feb 29 '16 at 18:11
  • Does it need to have 8 spaces before -crlf? – Igonato Sep 27 '17 at 09:50
  • Shouldn't matter – Trashman Sep 27 '17 at 11:22
  • 1
    This does more than just ignore the line endings for `git status`. It actually changes how files are checked into the repository. ref: https://git-scm.com/docs/gitattributes#_code_text_code – Vince Nov 14 '18 at 02:27
  • This does not help if you already have different line endings and like to see only what other changes to the files were made - adding this option will keep showing every file with changes only in line endings. – Thomas Tempelmann Jun 25 '19 at 12:02
  • can you explain what a "hard reset" is? – TemporaryFix Jul 24 '19 at 19:31
  • git reset --hard – Trashman Aug 29 '19 at 14:57
  • I've found using a .gitattribute file with settings appropriate to the project works well for my projects. There is a whole repo of useful .gitattributes for different languages and project types here: [.gitattributes templates](https://github.com/alexkaratarakis/gitattributes) – grahamesd Jul 28 '20 at 17:23
  • 1
    This has caused unchanged files to appear as changed, actually causes more problems then it solves – Luke Pring Feb 04 '21 at 11:43
  • Shouldn't the comment be `# Convert to CRLF line endings on checkout.`? It does not seem to ignore line changes but rather simply changing them, right? – J.Wincewicz Jul 01 '21 at 10:06
  • fyi, looks like `-crlf` is the same as `-text`. see https://git-scm.com/docs/gitattributes#_backwards_compatibility_with_crlf_attribute – starwarswii Oct 06 '21 at 19:19
  • Does not work for me, it still shows all eol changes in git and in phpstorm – Radon8472 Oct 12 '22 at 08:49
25

Issue related to git commands on Windows operating system:

$ git add --all

warning: LF will be replaced by CRLF in ...

The file will have its original line endings in your working directory.

Resolution:

$ git config --global core.autocrlf false     
$ git add --all 

No any warning messages come up.

Jim Jones
  • 18,404
  • 3
  • 35
  • 44
winstonhong
  • 1,214
  • 8
  • 8
  • you should do this in all OSs you are using, ie: in windows and in linux. Rember each OS has its own global .git/config file, so you need to make those settings simlar. This is why @Thorsten you were having problems. But I set the flag to true instead of false. – Emmanuel Mahuni Jun 07 '18 at 13:35
  • This solution works also in linux (the @SašaŠijak answer didn't works for me) – juliocesar Mar 10 '19 at 01:22
6

I created a script to ignore differences in line endings:

It will display the files which are not added to the commit list and were modified (after ignoring differences in line endings). You can add the argument "add" to add those files to your commit.

#!/usr/bin/perl

# Usage: ./gitdiff.pl [add]
#    add : add modified files to git

use warnings;
use strict;

my ($auto_add) = @ARGV;
if(!defined $auto_add) {
    $auto_add = "";
}

my @mods = `git status --porcelain 2>/dev/null | grep '^ M ' | cut -c4-`;
chomp(@mods);
for my $mod (@mods) {
    my $diff = `git diff -b $mod 2>/dev/null`;
    if($diff) {
        print $mod."\n";
        if($auto_add eq "add") {
            `git add $mod 2>/dev/null`;
        }
    }
}

Source code: https://github.com/lepe/scripts/blob/master/gitdiff.pl

Updates:

  • fix by evandro777 : When the file has space in filename or directory
lepe
  • 24,677
  • 9
  • 99
  • 108
  • Thanks! That's the only way i could get the real difference. There is just a problem that happened with 3 lines printed, showing this error: sh: 1: Syntax error: Unterminated quoted string – evandro777 Sep 06 '17 at 18:41
  • 1
    A fix for a script problem: The problem: When the file has space in filename ou directory, git will use "", so the script breaks. The fix is to change this line: my @mods = `git status --porcelain 2>/dev/null | grep '^ M ' | awk '{ print \$2 }'`; to this: my @mods = `git status --porcelain 2>/dev/null | grep '^ M ' | cut -c4-`; – evandro777 Sep 06 '17 at 19:19
  • @evandro777: Thanks! I have updated both, the answer and the git code. – lepe Sep 08 '17 at 01:10
5

I use both windows and linux, but the solution core.autocrlf true didn't help me. I even got nothing changed after git checkout <filename>.

So I use workaround to substitute git status - gitstatus.sh

#!/bin/bash

git status | grep modified | cut -d' ' -f 4 | while read x; do
 x1="$(git show HEAD:$x | md5sum | cut -d' ' -f 1 )"
 x2="$(cat $x | md5sum | cut -d' ' -f 1 )"

 if [ "$x1" != "$x2" ]; then
    echo "$x NOT IDENTICAL"
 fi
done

I just compare md5sum of a file and its brother at repository.

Example output:

$ ./gitstatus.sh
application/script.php NOT IDENTICAL
application/storage/logs/laravel.log NOT IDENTICAL
shukshin.ivan
  • 11,075
  • 4
  • 53
  • 69
  • 3
    perhaps you can use "git diff -b" for each file to check for changes excel whitespace changes – Ivan Dec 01 '16 at 15:27
  • It breaks if you have a space in your path. I tried to fix this with quoting the variables, but did not find a working way – Radon8472 Oct 12 '22 at 10:30
  • I found out that the problem was not the escaping, instead the `cut` was removing all content after the first space in path, this coult be fixed by changing `-f 4` in `-f4-` – Radon8472 Oct 12 '22 at 11:15
4

In vscode, just stage everything - the files that differ only by line endings should disappear, leaving behind only the files that differ in content. You can then unstage to get to the state you expected.

  • The question is not related to VScode, add this in comment to https://stackoverflow.com/questions/40779222/ignore-whitespace-in-visual-studio-code-git-diff-view – Reynadan Dec 20 '22 at 15:47
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/33406848) – Reynadan Dec 20 '22 at 15:48
  • This answer worked for me in a once only solution. If continuing to work between windows and linux, then a more permanent solution would be desirable. – John McCann Jan 06 '23 at 18:11
1

I've changed +shukshin.ivan script a bit - to ignore windows / linux line ending.

#!/bin/bash

git status | grep modified | cut -d' ' -f 4- | while read x; do
  d="$(git --no-pager diff --ignore-cr-at-eol $x)"

  if [ "$d" ]; then
    echo "$x NOT IDENTICAL"
  else
    echo "$x IDENTICAL"
    # uncomment the next line to undo the line ending changes
    # git checkout $x
  fi
done
Radon8472
  • 4,285
  • 1
  • 33
  • 41
Ohad Cohen
  • 5,756
  • 3
  • 39
  • 36
  • It breaks if you have a space in your path. I tried to fix this with quoting the variables, but did not find a working way – Radon8472 Oct 12 '22 at 10:36
  • I found out that the problem was not the escaping, instead the `cut` was removing all content after the first space in path, this coult be fixed by changing `-f 4` in `-f4-` – Radon8472 Oct 12 '22 at 11:13
0

In windows, set autocrlf to true:

git config --global core.autocrlf true

But this will only affect new files. Files already touched will still show up in git status as modified( even though the change is only in line endings)

to avoid this,Stash your local changes.

git stash

Apply them back:

git stash apply

when changes are reapplied git will be re-indexed and git will handle line endings properly. Hope this helps

arvin_v_s
  • 1,036
  • 1
  • 12
  • 18