Wenn Sie dies tun git diff
, wird "Kein Zeilenumbruch am Ende der Datei" angezeigt .
Ok, am Ende der Datei befindet sich kein Zeilenumbruch. Was ist die große Sache?
Welche Bedeutung hat die Nachricht und was versucht sie uns zu sagen?
Wenn Sie dies tun git diff
, wird "Kein Zeilenumbruch am Ende der Datei" angezeigt .
Ok, am Ende der Datei befindet sich kein Zeilenumbruch. Was ist die große Sache?
Welche Bedeutung hat die Nachricht und was versucht sie uns zu sagen?
Antworten:
Es zeigt an, dass Sie '\n'
am Ende der Datei keinen Zeilenumbruch haben (normalerweise auch bekannt als CR oder CRLF).
Das heißt, einfach gesagt, das letzte Byte (oder Bytes, wenn Sie unter Windows arbeiten) in der Datei ist keine neue Zeile.
Die Meldung wird angezeigt, da es ansonsten keine Möglichkeit gibt, den Unterschied zwischen einer Datei, in der am Ende eine neue Zeile steht, und einer Datei, in der dies nicht der Fall ist, zu erkennen. Diff muss sowieso eine neue Zeile ausgeben, sonst ist das Ergebnis schwerer zu lesen oder automatisch zu verarbeiten.
Beachten Sie, dass es ein guter Stil ist, die Zeilenumbruch immer als letztes Zeichen einzufügen, wenn das Dateiformat dies zulässt. Darüber hinaus ist es beispielsweise für C- und C ++ - Headerdateien vom Sprachstandard erforderlich.
Es ist nicht nur ein schlechter Stil, es kann zu unerwartetem Verhalten führen, wenn andere Tools in der Datei verwendet werden.
Hier ist test.txt
:
first line
second line
In der letzten Zeile befindet sich kein Zeilenumbruchzeichen. Mal sehen, wie viele Zeilen in der Datei sind:
$ wc -l test.txt
1 test.txt
Vielleicht ist es das, was Sie wollen, aber in den meisten Fällen würden Sie wahrscheinlich erwarten, dass die Datei zwei Zeilen enthält.
Wenn Sie Dateien kombinieren möchten, verhält es sich möglicherweise nicht so, wie Sie es erwarten:
$ cat test.txt test.txt
first line
second linefirst line
second line
Schließlich würde es Ihre Unterschiede etwas lauter machen, wenn Sie eine neue Zeile hinzufügen würden. Wenn Sie eine dritte Zeile hinzufügen, wird sowohl die zweite Zeile als auch die neue Zeile bearbeitet.
Der einzige Grund ist, dass Unix in der Vergangenheit eine Konvention für alle von Menschen lesbaren Textdateien hatte, die in einer neuen Zeile endeten. Zu diesem Zeitpunkt wurde eine zusätzliche Verarbeitung beim Anzeigen oder Verknüpfen von Textdateien vermieden und vermieden, dass Textdateien anders behandelt wurden als Dateien, die andere Arten von Daten enthalten (z. B. binäre Rohdaten, die nicht für Menschen lesbar sind).
Aufgrund dieser Konvention erwarten viele Tools aus dieser Zeit die abschließende Newline, einschließlich Texteditoren, unterschiedlichen Tools und anderen Textverarbeitungswerkzeugen. Mac OS X wurde auf BSD Unix aufgebaut, und Linux wurde so entwickelt, dass es Unix-kompatibel ist. Daher haben beide Betriebssysteme die gleiche Konvention, das gleiche Verhalten und die gleichen Tools geerbt.
Windows wurde nicht als Unix-kompatibel entwickelt, daher hat es nicht die gleiche Konvention, und die meisten Windows-Programme funktionieren ohne nachfolgende Zeilenumbrüche einwandfrei.
Da Git jedoch zuerst für Linux entwickelt wurde und viele Open-Source-Programme auf Unix-kompatiblen Systemen wie Linux, Mac OS X, FreeBSD usw. basieren, werden die meisten Open-Source-Communities und ihre Tools (einschließlich Programmiersprachen) fortgesetzt diese Konventionen zu befolgen.
Es gibt technische Gründe, die 1971 Sinn machten, aber in dieser Zeit ist es meistens Konvention und Aufrechterhaltung der Kompatibilität mit vorhandenen Werkzeugen.
Wenn Sie am Ende der vorhandenen Datei eine neue Textzeile hinzufügen, die am Ende noch keine enthält newline character
, zeigt der Diff die alte letzte Zeile als geändert an, obwohl dies konzeptionell nicht der Fall war.
Dies ist mindestens ein guter Grund, newline character
am Ende ein hinzuzufügen .
Eine Datei enthält:
A() {
// do something
}
Hexdump:
00000000: 4128 2920 7b0a 2020 2020 2f2f 2064 6f20 A() {. // do
00000010: 736f 6d65 7468 696e 670a 7d something.}
Sie bearbeiten es jetzt zu
A() {
// do something
}
// Useful comment
Hexdump:
00000000: 4128 2920 7b0a 2020 2020 2f2f 2064 6f20 A() {. // do
00000010: 736f 6d65 7468 696e 670a 7d0a 2f2f 2055 something.}.// U
00000020: 7365 6675 6c20 636f 6d6d 656e 742e 0a seful comment..
Das Git Diff zeigt:
-}
\ No newline at end of file
+}
+// Useful comment.
Mit anderen Worten, es zeigt einen größeren Unterschied als konzeptionell aufgetreten. Es zeigt, dass Sie die Zeile gelöscht }
und hinzugefügt haben }\n
. Dies ist in der Tat das, was passiert ist, aber es ist nicht das, was konzeptionell passiert ist, also kann es verwirrend sein.
Der Grund, warum diese Konvention in die Praxis umgesetzt wurde, liegt darin, dass unter UNIX-ähnlichen Betriebssystemen ein Zeilenumbruchzeichen als Zeilenabschluss und / oder Nachrichtengrenze behandelt wird (dies umfasst das Weiterleiten zwischen Prozessen, Zeilenpufferung usw.).
Stellen Sie sich zum Beispiel vor, dass eine Datei mit nur einem Zeilenumbruchzeichen als einzelne leere Zeile behandelt wird. Umgekehrt ist eine Datei mit einer Länge von null Bytes tatsächlich eine leere Datei mit null Zeilen. Dies kann gemäß dem wc -l
Befehl bestätigt werden .
Insgesamt ist dieses Verhalten sinnvoll, da es keine andere Möglichkeit gibt, zwischen einer leeren Textdatei und einer Textdatei mit einer einzelnen leeren Zeile zu unterscheiden, wenn das \n
Zeichen lediglich ein Zeilentrennzeichen und kein Zeilenendezeichen wäre. Gültige Textdateien sollten daher immer mit einem Zeilenumbruchzeichen enden. Die einzige Ausnahme ist, wenn die Textdatei leer sein soll (keine Zeilen).
Es gibt eine Sache, die ich in früheren Antworten nicht sehe. Die Warnung, dass kein Zeilenende vorhanden ist, kann eine Warnung sein, wenn ein Teil einer Datei abgeschnitten wurde. Dies könnte ein Symptom für fehlende Daten sein.
Das Kernproblem besteht darin, was Sie als Zeile definieren und ob die Zeichenfolge am Ende der Zeile Teil der Zeile ist oder nicht. UNIX-basierte Editoren (wie VIM) oder Tools (wie Git) verwenden die EOL-Zeichenfolge als Zeilenabschluss, daher ist sie Teil der Zeile. Es ähnelt der Verwendung von Semikolon (;) in C und Pascal. In C beendet das Semikolon Anweisungen, in Pascal werden sie getrennt.
Dies verursacht tatsächlich ein Problem, da Zeilenenden automatisch geändert werden, um Dateien zu verschmutzen, ohne Änderungen daran vorzunehmen. Siehe diesen Beitrag zur Lösung.
Quelldateien werden häufig von Tools verkettet (C, C ++: Header-Dateien, Javascript: Bundler). Wenn Sie das Zeilenumbruchzeichen weglassen, können böse Fehler auftreten (wobei die letzte Zeile einer Quelle mit der ersten Zeile der nächsten Quelldatei verknüpft ist). Hoffentlich fügen alle Quellcode-Concat-Tools eine neue Zeile zwischen verketteten Dateien ein, aber das scheint nicht immer der Fall zu sein.
Der Kern des Problems ist: In den meisten Sprachen haben Zeilenumbrüche eine semantische Bedeutung, und das Dateiende ist keine sprachdefinierte Alternative für das Zeilenumbruchzeichen. Sie sollten also jede Anweisung / jeden Ausdruck mit einem Zeilenumbruchzeichen beenden - einschließlich des letzten.
//
Stilkommentar in der Mitte des Codes verwenden.
Ihre Originaldatei hatte wahrscheinlich kein Zeilenumbruchzeichen.
Einige Editoren wie gedit unter Linux fügen jedoch stillschweigend Zeilenumbrüche am Ende der Datei hinzu. Sie können diese Meldung nicht entfernen, wenn Sie diese Art von Editoren verwenden.
Ich habe versucht, dieses Problem zu beheben, indem ich die Datei mit dem Visual Studio Code Editor geöffnet habe
Dieser Editor zeigt deutlich die letzte Zeile an und Sie können die Zeile nach Belieben löschen.
Ich bin darauf gestoßen, als ich ein IntelliJ-Projekt auf einem Mac erstellt und das Projekt dann auf meinen Windows-Computer verschoben habe. Ich musste jede Datei manuell öffnen und die Codierungseinstellung unten rechts im IntelliJ-Fenster ändern. Wahrscheinlich nicht den meisten, die diese Frage gelesen haben, aber das hätte mir ein paar Stunden Arbeit ersparen können ...