Avoid “No newline at end of file” in git diff
Avoid “No newline at end of file” in git diff
I'm quite sure I understand what No newline at end of file means. I want to provide a pull request of a branch which I created long time ago and rebased (commits might be from the time before .gitattributes
has been added). I see that some .java
source code files have only the change
.gitattributes
.java
-}
No newline at end of file
+}
regardless of the configuration, I'd simply like these changes to be excluded from the PR commit. I'd like to avoid picking the changes with git difftool
and broaden my understanding of git
.
git difftool
git
The thing is that I already don't understand how this change can exist since there's a .gitattributes
with
.gitattributes
# 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
*.java text
*.css text
*.js text
*.xml text
*.dtd text
*.xsl text
*.properties text
*.txt text
*.svg text
*.yml text
*.md 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
*.gif binary
*.jpg binary
*.jpeg binary
*.eot binary
*.ttf binary
*.woff binary
*.woff2 binary
in the repository and I ran git rm --cached -r . && git add .
which should convert all line endings to LF because of *.java text
(also tried *.java text
), but there're no changes shown (against HEAD
) and git diff
still shows the line ending difference.
git rm --cached -r . && git add .
*.java text
*.java text
HEAD
git diff
Also find ./ -type f -name '*.java' -exec dos2unix ;
doesn't causes any changes to be recognized by git status
and git diff master
still displays the line ending change (while the working directory has no staged or unstaged changes).
find ./ -type f -name '*.java' -exec dos2unix ;
git status
git diff master
I'm not interested in hiding the changes, like git diff --ignore-all-space
would do.
git diff --ignore-all-space
I'm using git
2.17.1 on Ubuntu 18.04.
git
1 Answer
1
The thing is that I already don't understand how this change can exist ...
The change shows that the a/
version of the whatever.java
file is missing a newline, while the b/
version of the file has one. "Missing a newline" means that the file ends with no line terminator—it's not a question of CRLF vs LF, it's a question of "has terminator" vs "does not have terminator".
a/
whatever.java
b/
Some editors are capable of handling files that have a final line that lacks a terminator. Other editors are not and don't even notice that there is one missing (mostly just pretending there was one). Some editors will default to adding a terminator if it seems appropriate, perhaps with a warning. There is a lot of variation here.
You don't show what particular git diff
command (with what options) generated the diff, so it's hard to say where the a/
and b/
versions came from, but I'll assume HEAD
commit and either-index
-or-work-tree below. (That is, we're looking at trimmed git diff --cached
or git diff HEAD
output. Either way we'll see the same thing since git diff
has to run the work-tree file through any clean
filter and any end-of-line filtering.)
git diff
a/
b/
HEAD
index
git diff --cached
git diff HEAD
git diff
clean
... since there's a .gitattributes
[that includes]
.gitattributes
*.java text
... and I ran git rm --cached -r . && git add .
which should convert all line endings to LF ...
git rm --cached -r . && git add .
This will convert any existing CRLF line endings in the work-tree to LF-only line endings in the index. I do not believe it will an add LF-ending to lines that have no ending at all (based on the code in crlf_to_git
in convert.c
).
crlf_to_git
convert.c
So, that suggests that your work-tree copy of the file has a final CRLF as the last two bytes of the file, or a final LF-only newline byte as the last single byte of the file. Git would git add
that as a final newline. Meanwhile, if the commit itself has a lone close-curly brace (with no line endings at all, neither CRLF nor newlne) as its final byte, that means that the committed (HEAD
) copy of the file differs from the index version of the same file by having the committed copy lack any line terminator at all, and you'd see just what you do see.
git add
HEAD
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.