Нет новой строки в конце файла

при выполнении git diff Он говорит: "нет новой строки в конце файла".

Ok, в конце файла нет новой строки. В чем проблема?

каково значение сообщения и что оно пытается нам сказать?

12 ответов


Это означает, что у вас нет строки (обычно '\n', aka CR или CRLF) в конце файла.

то есть, проще говоря, последний байт (или байты, если вы находитесь в Windows) в файле не является новой строкой.

сообщение отображается, потому что в противном случае невозможно определить разницу между файлом, в конце которого есть новая строка, и файлом, в котором ее нет. Diff должен вывести новую строку в любом случае, или результат будет сложнее прочитать или обработать автоматически.

обратите внимание, что это хороший стиль, чтобы всегда ставить новую строку в качестве последнего символа, если это разрешено форматом файла. Кроме того, например, для заголовочных файлов C и C++ это требуется стандартом языка.


это не просто плохой стиль, это может привести к неожиданному поведению при использовании других инструментов в файле.

здесь test.txt:

first line
second line

в последней строке нет символа новой строки. Давайте посмотрим, сколько строк в файле:

$ wc -l test.txt
1 test.txt

может быть, это то, что вы хотите, но в большинстве случаев вы, вероятно, ожидаете, что в файле будет 2 строки.

кроме того, если вы хотите объединить файлы, он может вести себя не так, как вы ожидайте:

$ cat test.txt test.txt
first line
second linefirst line
second line

наконец, это сделает ваши различия немного более шумными, если вы добавите новую строку. Если вы добавили третью строку, она покажет редактирование второй строки, а также новое добавление.


Это просто указывает на то, что в конце файла нет новой строки. Это не катастрофа, это просто сообщение, чтобы прояснить, что его нет, когда вы смотрите на разницу в командной строке.


Если вы добавите новую строку в конце существующего файла, у которого уже нет новой строки в конце, diff покажет старую последнюю строку также как измененную, когда концептуально ее нет.

по крайней мере, одна веская причина добавить новую строку в конце.


единственная причина в том, что Unix исторически имел соглашение всех читаемых человеком текстовых файлов, заканчивающихся новой строкой. В то время это позволило избежать дополнительной обработки при отображении или объединении текстовых файлов и избежать обработки текстовых файлов по-разному с файлами, содержащими другие виды данных (например, необработанные двоичные данные, которые не читаются человеком).

из - за этого соглашения многие инструменты той эпохи ожидают окончания новой строки, включая текстовые редакторы, различные инструменты и другой текст инструменты обработки. Mac OS X был построен на BSD Unix, а Linux был разработан как Unix-совместимый, поэтому обе операционные системы унаследовали одно и то же соглашение, поведение и инструменты.

Windows не была разработана для совместимости с Unix, поэтому она не имеет того же соглашения, и большинство программного обеспечения Windows будет иметь дело просто отлично без конечной новой строки.

но, поскольку Git был разработан для Linux первым, и много программного обеспечения с открытым исходным кодом построено на Unix-совместимых системах, таких как Linux, Mac OS X, FreeBSD и т. д. Большинство сообществ с открытым исходным кодом и их инструменты (включая языки программирования) продолжают следовать этим соглашениям.

есть технические причины, которые имели смысл в 1971 году, но в эту эпоху это в основном конвенция и поддержание совместимости с существующими инструментами.


основная проблема заключается в том, что вы определяете линию и являетесь ли end-on-line последовательность символов является частью строки или нет. Редакция ОС UNIX (например, VIM) или инструменты (например, Git) используют последовательность символов EOL как линия Терминатор, следовательно, это часть линии. Это похоже на использование точки с запятой (;) в C и Pascal. В C точка с запятой завершается утверждения, в Паскале он разделяет их.


Это на самом деле вызывает проблему, потому что окончания строк автоматически изменяются, загрязняя файлы без каких-либо изменений в них. См. это сообщение для разрешения.

git замена LF на CRLF


есть одна вещь, которую я не вижу в предыдущих ответах. Предупреждение об отсутствии конца строки может быть предупреждением при усечении части файла. Это может быть симптомом отсутствия данных.


ваш исходный файл, вероятно, не было символа новой строки.

однако некоторым редакторам нравится gedit в linux молча добавляет новую строку в конце файла. Вы не можете избавиться от этого сообщения при использовании такого рода редакторов.

Что я пытался преодолеть эту проблему, чтобы открыть файл с редактор кода visual studio

этот редактор явно показывает последнюю строку, и вы можете удалить строку, как вы хотите.


исходные файлы часто объединяются инструментами (C, C++: header files, Javascript: bundlers). Если вы опустите символ новой строки, вы можете ввести неприятные ошибки (где последняя строка одного источника объединена с первой строкой следующего исходного файла). Надеюсь, все инструменты исходного кода concat там вставляют новую строку между объединенными файлами, но это не всегда так.

суть проблемы в том, что в большинстве языков новые строки имеют семантическое значение и конец файла не является альтернативой языка, определенного для символа новой строки. Поэтому вы должны завершить каждый оператор / выражение символом новой строки, включая последний.


для чего это стоит, я столкнулся с этим, когда я создал проект IntelliJ на Mac, а затем переместил проект на свою машину Windows. Мне пришлось вручную открыть каждый файл и изменить настройку кодировки в правом нижнем углу окна IntelliJ. Вероятно, это не происходит с большинством, если кто-то читает этот вопрос, но это могло бы сэкономить мне пару часов работы...


причина, по которой это соглашение вступило в практику, заключается в том, что в UNIX-подобных операционных системах символ новой строки рассматривается как Терминатор строки и/или граница сообщения (это включает в себя конвейер между процессами, буферизацию строк и т. д.).

рассмотрим, например, что файл с символом новой строки рассматривается как одна пустая строка. И наоборот, файл с длиной нулевых байтов на самом деле является пустым файлом с нулевыми строками. Это можно подтвердить в соответствии с wc -l команда.

в целом, это поведение разумно, потому что не было бы другого способа отличить пустой текстовый файл от текстового файла с одной пустой строкой, если был просто разделителем строк, а не Терминатором строк. Таким образом, допустимые текстовые файлы всегда должны заканчиваться символом новой строки. Единственное исключение - если текстовый файл должен быть пустым (без строк).