Patches in Code-Reviews, Fehlerberichten und E-Mails liegen meist im Unified-Diff-Format vor. git diff, diff -u und das „raw diff“ von GitHub verwenden alle dieses Format. Anfangs wirkt es wegen der vielen Symbole unübersichtlich, doch die Regeln sind einfach.
Der Gesamtaufbau
@@ -1,5 +1,6 @@ def greet(name):- print("Hello " + name)+ message = f"Hello, {name}!"+ print(message) def main(): greet("world")
Von oben nach unten folgen erweiterte git-Header, Datei-Header (---, +++) und Hunks (Blöcke, die mit @@ beginnen). Eine Datei kann mehrere Hunks enthalten, ein Patch mehrere Dateien.
Datei-Header: --- und +++
--- a/greet.pyist die Datei vor der Änderung,+++ b/greet.pydie Datei nach der Änderung.- git setzt
a/undb/vor die Pfade. Beim Anwenden mit dem Befehlpatchentfernt man deshalb mit-p1die erste Pfadkomponente. - Eine neu angelegte Datei wird als
--- /dev/null, eine gelöschte als+++ /dev/nullangezeigt. - GNU diff hängt an den Dateinamen manchmal noch den Änderungszeitpunkt an.
Der Hunk-Header @@ -a,b +c,d @@
@@ -1,5 +1,6 @@ bedeutet: „Gezeigt werden 5 Zeilen ab Zeile 1 der alten Datei und 6 Zeilen ab Zeile 1 der neuen Datei.“
- Die erste Zahl ist die Startzeile, die Zahl nach dem Komma die Zahl der Zeilen im Hunk (einschließlich Kontextzeilen).
- Ist die Zeilenzahl 1, entfallen Komma und Zahl.
@@ -7 +7 @@ist ein Hunk, der nur aus Zeile 7 besteht. - Ist die Zeilenzahl 0, gibt es auf dieser Seite keine Zeilen.
@@ -3,0 +4,2 @@bedeutet, dass nach Zeile 3 des Originals zwei neue Zeilen eingefügt wurden. Beim Vergleich mit einer leeren Datei erscheint-0,0. - Hinter dem zweiten
@@steht manchmal Text wie ein Funktionsname (@@ -40,7 +40,8 @@ def main():). Das ist nur ein Hinweis, in welcher Funktion der Hunk liegt, und wird beim Anwenden ignoriert.
Zählt man nach, hat das Beispiel oben 4 Kontextzeilen (Zeilen, die mit einem Leerzeichen beginnen): def greet(name):, eine Leerzeile, def main(): und greet("world"). Vorher sind es 4 Kontextzeilen plus 1 --Zeile = 5, nachher 4 Kontextzeilen plus 2 +-Zeilen = 6 — daher lautet der Header -1,5 +1,6.
Die drei Zeilenarten im Hunk
| Erstes Zeichen | Bedeutung |
|---|---|
| Leerzeichen | Kontextzeile, auf beiden Seiten gleich |
- | Zeile nur vor der Änderung (gelöscht) |
+ | Zeile nur nach der Änderung (hinzugefügt) |
Standardmäßig werden 3 Kontextzeilen vor und nach einer Änderung gezeigt (änderbar, z. B. mit git diff -U5). Kontextzeilen dienen beim Anwenden eines Patches dazu, die richtige Stelle zu finden. Auch wenn die Zeilennummern leicht abweichen, wendet patch den Hunk mit Versatz (offset) an, solange der Kontext passt.
Eine geänderte Zeile erscheint als Paar aus einer --Zeile, gefolgt von einer +-Zeile. Das Unified-Format hat kein eigenes Symbol für „geändert“; es hilft, einen zusammenhängenden --Block und den folgenden +-Block untereinander abzugleichen.
\ No newline at end of file
@@ -1,2 +1,2 @@ host=example.com-port=8080\ No newline at end of file+port=8080
Dieser Hinweis bedeutet, dass die Zeile direkt darüber die letzte Zeile der Datei ist und am Ende kein Zeilenumbruchzeichen hat. Im Beispiel ist der Inhalt gleich; nur die neue Datei hat einen abschließenden Zeilenumbruch bekommen. Mehr dazu unter Zeilenenden und unsichtbare Unterschiede.
Erweiterte git-Header
Die Zeilen nach diff --git a/pfad b/pfad sind Zusatzinformationen, die nur git liefert.
index 3b18e51..a6f4c2d 100644— Anfang der Hashes des Dateiinhalts vor und nach der Änderung sowie der Dateimodus (100644 ist eine normale Datei, 100755 eine ausführbare)new file mode 100644/deleted file mode 100644— Datei angelegt / gelöschtold mode 100644/new mode 100755— nur die Ausführungsrechte haben sich geändert (kann ohne Inhalts-Hunk erscheinen)similarity index 90%,rename from alter-pfad,rename to neuer-pfad— Umbenennung (der Inhalt ist zu 90 % gleich)Binary files a/logo.png and b/logo.png differ— bei Binärdateien steht statt des Inhalts nur diese eine Zeile
Nützliche Tipps für Reviews
- Ein Blick auf den Unterschied der Zeilenzahlen im Hunk-Header verrät die Größe der Änderung. Bei
-10,7 +10,30sind 23 Zeilen hinzugekommen. - Um Hunks auszublenden, in denen sich nur Leerraum geändert hat, verwenden Sie
git diff -w. Das ist besonders nützlich bei Commits, die Einrückungskorrekturen und echte Änderungen mischen (Optionen zum Ignorieren von Leerraum). - Um zu sehen, was sich innerhalb einer Zeile geändert hat, verwenden Sie
git diff --word-diffoder ein Werkzeug mit Hervorhebung innerhalb der Zeile wie diese Seite. - Prüfen Sie vor dem Anwenden eines Patches mit
git apply --check datei.patch, ob er sich sauber anwenden lässt. Außerhalb eines git-Repositorys nehmen Siepatch -p1 --dry-run < datei.patch.
In diesem Werkzeug ausprobieren
Die vereinheitlichte Ansicht im Textvergleich zeigt in derselben Reihenfolge wie dieses Format zuerst den --Block und dann den +-Block und hebt die geänderten Wörter innerhalb der Zeile zusätzlich hervor. Die Schaltfläche patch in der Ergebnisleiste kopiert einen standardkonformen Unified-Diff-Text, die Speichern-Schaltfläche daneben lädt ihn als Datei diff.patch herunter. Ein Patch, der mit ausgeschalteten Ignorieroptionen erzeugt wurde, lässt sich mit patch -p1 oder git apply auf das Original anwenden.