So wenden Sie unter Linux einen Patch auf eine Datei an (und erstellen Patches)

Der Linux-Befehl `patch` ermöglicht es Ihnen, Änderungen von einem Satz von Dateien auf einen anderen Satz schnell und zuverlässig zu übertragen. In diesem Artikel erfahren Sie, wie Sie `patch` auf einfache Weise einsetzen können.

Die Befehle `patch` und `diff`

Stellen Sie sich vor, Sie haben eine Textdatei auf Ihrem Computer. Nun erhalten Sie eine veränderte Version dieser Datei von jemand anderem. Wie können Sie schnell alle Änderungen der neuen Datei in Ihre Originaldatei übertragen? Hier kommen `patch` und `diff` ins Spiel. Diese Befehle sind auf Linux und anderen Unix-ähnlichen Systemen wie macOS verfügbar.

Der Befehl `diff` analysiert zwei Dateiversionen und gibt die Unterschiede aus. Diese Unterschiede lassen sich in einer sogenannten Patch-Datei speichern.

Der Befehl `patch` ist in der Lage, eine Patch-Datei zu lesen und deren Inhalt als eine Abfolge von Anweisungen zu interpretieren. Diese Anweisungen ermöglichen es, die Änderungen der modifizierten Datei in der Originaldatei nachzuvollziehen.

Stellen Sie sich diesen Vorgang für ein ganzes Verzeichnis von Textdateien vor – und zwar auf einmal. Das ist die Stärke von `patch`.

In manchen Fällen erhalten Sie nicht die geänderten Dateien, sondern lediglich die Patch-Datei. Warum auch Dutzende von Dateien versenden, wenn eine einzige Datei zum Senden oder Herunterladen bereitgestellt werden kann?

Wie setzen Sie nun die Patch-Datei ein, um Ihre Dateien tatsächlich zu „patchen“? Diese berechtigte Frage werden wir in diesem Artikel beantworten.

Der `patch`-Befehl wird häufig von Personen verwendet, die mit Software-Quellcode arbeiten, ist aber für alle Arten von Textdateien geeignet, ob Quellcode oder nicht.

Unser Beispielszenario

Wir gehen von einem Verzeichnis namens „work“ aus, das zwei weitere Unterverzeichnisse enthält: „working“ und „latest“. Das „working“-Verzeichnis enthält eine Reihe von Quellcodedateien, während das „latest“-Verzeichnis die aktuellste Version dieser Dateien enthält, wobei einige davon verändert wurden.

Das „working“-Verzeichnis ist eine Sicherheitskopie der ursprünglichen Version der Textdateien, nicht ihre einzige Kopie.

Die Unterschiede zwischen zwei Dateiversionen ermitteln

Der Befehl `diff` findet die Unterschiede zwischen zwei Dateien. Standardmäßig werden die geänderten Zeilen im Terminalfenster ausgegeben.

Eine der Dateien heißt „slang.c“. Wir vergleichen die Version im „working“-Verzeichnis mit der im „latest“-Verzeichnis.

Die Option `-u` (unified) bewirkt, dass `diff` zusätzlich einige der unveränderten Textzeilen vor und nach jedem geänderten Abschnitt ausgibt. Diese Zeilen werden Kontextzeilen genannt und helfen `patch`, die genaue Position der Änderungen in der Originaldatei zu bestimmen.

Wir geben die Dateinamen an, damit `diff` weiß, welche Dateien verglichen werden sollen. Die Originaldatei steht zuerst, dann die geänderte Datei. Der Befehl lautet:

diff -u working/slang.c latest/slang.c

`diff` gibt eine Liste aus, die die Unterschiede zwischen den Dateien anzeigt. Wenn die Dateien identisch wären, gäbe es keine Ausgabe. Diese Ausgabe bestätigt, dass es Unterschiede gibt und dass die Originaldatei gepatcht werden muss.

Eine Patch-Datei erstellen

Mit dem folgenden Befehl können Sie die Unterschiede in einer Patch-Datei speichern. Es ist derselbe Befehl wie zuvor, aber die Ausgabe von `diff` wird in eine Datei namens „slang.patch“ umgeleitet:

diff -u working/slang.c latest/slang.c > slang.patch

Um die Patch-Datei auf die Datei „working/slang.c“ anzuwenden, verwenden Sie folgenden Befehl. Die Option `-u` (unified) teilt `patch` mit, dass die Patch-Datei vereinheitlichte Kontextzeilen enthält. Das heißt, da wir `-u` mit `diff` benutzt haben, verwenden wir auch `-u` mit `patch`.

patch -u working/slang.c -i slang.patch

Wenn alles gut geht, erhalten Sie eine Bestätigung, dass die Datei gepatcht wurde.

Eine Sicherheitskopie der Originaldatei erstellen

Wir können `patch` anweisen, eine Sicherungskopie der Dateien zu erstellen, bevor sie verändert werden. Dies erreichen wir mit der Option `-b` (Backup). Die Option `-i` (input) teilt `patch` den Namen der zu verwendenden Patch-Datei mit:

patch -u -b working/slang.c -i slang.patch

Die Datei wird wie zuvor gepatcht, ohne sichtbare Unterschiede in der Ausgabe. Wenn Sie jedoch das „working“-Verzeichnis überprüfen, sehen Sie, dass eine Datei namens „slang.c.orig“ erstellt wurde. Die Zeitstempel zeigen, dass „slang.c.orig“ die Originaldatei ist, während „slang.c“ die von `patch` neu erstellte Datei ist.

`diff` mit Verzeichnissen verwenden

Wir können `diff` verwenden, um eine Patch-Datei zu erstellen, die alle Unterschiede zwischen Dateien in zwei Verzeichnissen beinhaltet. Mit dieser Datei können wir dann die Änderungen mit einem einzigen `patch`-Befehl auf die Dateien im „working“-Verzeichnis anwenden.

Die Optionen, die wir mit `diff` verwenden, sind `-u` (unified context), `-r` (rekursiv, für die Suche in Unterverzeichnissen) und `-N` (neue Datei).

Die Option `-N` erklärt `diff`, wie mit Dateien im „latest“-Verzeichnis umzugehen ist, die im „working“-Verzeichnis nicht existieren. Sie zwingt `diff`, Anweisungen in die Patch-Datei aufzunehmen, sodass `patch` diese neuen Dateien im „working“-Verzeichnis erstellt.

Die Optionen können zusammengefasst werden:

Beachten Sie, dass wir nur die Verzeichnisnamen angeben und `diff` nicht anweisen, bestimmte Dateien zu suchen:

diff -ruN working/ latest/ > slang.patch

Der Anfang der Datei zeigt die Unterschiede zwischen den beiden Versionen von „slang.c“.

Weiter unten sehen wir, dass die Datei auch die Änderungen in einer Datei namens „structs.h“ beschreibt. Die Patch-Datei enthält also definitiv die Unterschiede zwischen verschiedenen Versionen mehrerer Dateien.

Sicherheitsüberprüfung vor dem Anwenden

Das Patchen einer großen Anzahl von Dateien kann riskant sein. Deshalb verwenden wir die Option `–dry-run`, um zu prüfen, ob alles in Ordnung ist, bevor wir die Änderungen wirklich anwenden.

Die Option `–dry-run` weist `patch` an, alles zu tun, außer die Dateien tatsächlich zu ändern. `patch` führt alle Vorabprüfungen durch und meldet etwaige Probleme. Es werden keine Dateien verändert.

Wenn keine Fehler gemeldet werden, können wir den Befehl ohne `–dry-run` ausführen und unsere Dateien bedenkenlos patchen.

Die Option `-d` (directory) teilt `patch` mit, in welchem Verzeichnis gearbeitet werden soll.

Beachten Sie, dass wir nicht die Option `-i` (input) verwenden, um `patch` mitzuteilen, welche Patch-Datei die Anweisungen von `diff` enthält. Stattdessen leiten wir die Patch-Datei mittels `<` in `patch` um.

patch --dry-run -ruN -d working  < slang.patch

Von allen Dateien im Verzeichnis hat `diff` zwei zum Patchen gefunden. Die Anweisungen für die Änderungen dieser zwei Dateien wurden von `patch` überprüft, und es wurden keine Probleme festgestellt.

Die Vorabprüfungen sind erfolgreich, wir können mit dem Patchen beginnen.

Ein Verzeichnis patchen

Um die Patches wirklich auf die Dateien anzuwenden, verwenden wir den vorherigen Befehl ohne die Option `–dry-run`.

patch -ruN -d working  < slang.patch

Dieses Mal beginnt jede Ausgabezeile mit „patching“ anstatt mit „checking“.

Es wurden keine Probleme gemeldet. Wir können unseren Quellcode kompilieren und verfügen somit über die neueste Softwareversion.

Unterschiede bereinigen

Dies ist mit Abstand die einfachste und sicherste Art, `patch` zu verwenden. Kopieren Sie Ihre Zieldateien in einen Ordner und patchen Sie diesen Ordner. Kopieren Sie die Dateien zurück, wenn Sie sicher sind, dass der Patchvorgang fehlerfrei abgeschlossen wurde.