Commits als versendbare Patch-Dateien statt als Merge Request
Nicht jedes Git-Projekt läuft über ein zentrales Forge mit Pull-Request-Oberfläche. git format-patch erzeugt aus einer Reihe von Commits versendbare Patch-Dateien, die Empfänger mit git am wieder zu vollständigen Commits zusammensetzen können, ganz ohne GitHub, GitLab oder ein anderes Web-Interface dazwischen. Dieser Artikel zeigt, wie sich Patch-Serien erzeugen, mit einem Cover Letter versehen, versionieren und über git send-email verschicken lassen, und wann sich dieser Workflow gegenüber Pull Requests tatsächlich lohnt.
Inhaltsverzeichnis
- 1. Grundidee: Commits als Patch-Dateien statt als Pull Request
- 2. git format-patch: Aufbau der erzeugten Dateien
- 3. Eine Patch-Serie mit Cover Letter erzeugen
- 4. Patches per E-Mail versenden mit git send-email
- 5. Patch-Serien versionieren mit v2, v3 und Reroll-Count
- 6. Serien miteinander vergleichen mit git range-diff
- 7. Empfängerseite: Patches prüfen und anwenden
- 8. Wann sich der patch-basierte Workflow gegenüber Pull Requests lohnt
- 9. Praktische Stolperfallen und Checkliste für den Einstieg
- 10. Zusammenfassung
- 11. FAQ
1. Grundidee: Commits als Patch-Dateien statt als Pull Request
Ein Pull Request ist im Kern ein Verweis auf zwei Branches, die auf einem zentralen Server verglichen werden. Diese zentrale Instanz existiert in vielen dezentral organisierten Projekten schlicht nicht, oder sie wird bewusst vermieden, etwa weil ein Projekt seit Jahrzehnten über eine Mailingliste organisiert ist und niemand die etablierten Abläufe einer eingespielten Beitrags- und Review-Kultur aufgeben möchte.
git format-patch löst diese Abhängigkeit von einer zentralen Instanz vollständig auf: Jeder Commit wird in eine eigenständige, textbasierte Datei umgewandelt, die alle nötigen Informationen enthält, um beim Empfänger wieder zu einem identischen Commit zu werden. Übertragen werden kann diese Datei über praktisch jeden Kanal, eine E-Mail, einen USB-Stick oder ein einfaches Dateiablage-System.
2. git format-patch: Aufbau der erzeugten Dateien
Ohne weitere Optionen erzeugt git format-patch für jeden Commit im angegebenen Bereich eine eigene Datei, benannt nach einer fortlaufenden Nummer und der aus der Commit-Betreffzeile abgeleiteten Kurzbeschreibung, etwa 0001-fix-cache-invalidation.patch. Jede dieser Dateien enthält die vollständigen E-Mail-Header mit Autor und Datum, die komplette Commit-Nachricht und den zugehörigen Diff im unified-diff-Format.
Als Bereich lässt sich entweder eine einzelne Commit-Referenz angeben, wodurch alle Commits seit diesem Punkt bis HEAD exportiert werden, oder ein expliziter Zwei-Punkt-Bereich zwischen zwei Commits. Die Option -o bestimmt dabei das Zielverzeichnis für die erzeugten Dateien, was sich gut eignet, um mehrere Serien sauber voneinander getrennt zu halten.
# Alle Commits seit dem Abzweigen von main als Patch-Dateien exportieren
git format-patch main --output-directory patches/
# Genau die letzten drei Commits exportieren
git format-patch -3
3. Eine Patch-Serie mit Cover Letter erzeugen
Bei mehreren zusammengehörigen Commits ist eine kurze, einleitende Beschreibung der gesamten Serie hilfreich, bevor der Empfänger jeden einzelnen Patch im Detail liest. Die Option --cover-letter erzeugt dafür automatisch eine zusätzliche Datei mit der Nummer 0000, die als Platzhalter für eine solche Zusammenfassung dient und vor dem Versand von Hand mit Motivation, Überblick und relevanten Hintergrundinformationen gefüllt werden sollte.
In Kombination mit -N beziehungsweise der automatisch aktivierten Nummerierung ab zwei Patches zeigt jede Datei zusätzlich an, um den wievielten Teil einer Gesamtserie es sich handelt, etwa [PATCH 2/5] in der Betreffzeile, was Empfängern sofort einen Überblick über Umfang und Position innerhalb der Serie gibt.
# Patch-Serie inklusive Cover-Letter-Datei erzeugen
git format-patch main --cover-letter --output-directory patches/
4. Patches per E-Mail versenden mit git send-email
Statt erzeugte Patch-Dateien manuell als Anhang zu versenden, was viele Mail-Clients durch automatische Umformatierung unbrauchbar macht, bindet git send-email direkt an einen konfigurierten SMTP-Server an und verschickt jede Patch-Datei als eigene, reine Text-E-Mail mit korrekt gesetzten Headern, sodass die enthaltenen Diffs beim Empfänger unverändert ankommen.
Die Konfiguration erfolgt einmalig über git config sendemail.smtpserver und die zugehörigen Zugangsdaten, danach genügt git send-email patches/*.patch, um eine gesamte Serie inklusive Cover Letter in der richtigen Reihenfolge und mit korrekt verketteten In-Reply-To-Headern als zusammenhängenden Thread zu verschicken.
# SMTP-Server einmalig konfigurieren
git config sendemail.smtpserver smtp.mironsoft.internal
git config sendemail.smtpserverport 587
# Gesamte Serie als zusammenhängenden E-Mail-Thread verschicken
git send-email --to=team@mironsoft.de patches/*.patch
5. Patch-Serien versionieren mit v2, v3 und Reroll-Count
Erhält eine bereits versendete Serie nach Rückmeldungen eine überarbeitete Fassung, wird sie üblicherweise nicht kommentarlos erneut verschickt, sondern klar als neue Version gekennzeichnet. Die Option --subject-prefix erlaubt es, das Standardpräfix PATCH in der Betreffzeile durch einen eigenen Text zu ersetzen, etwa PATCH v2, wodurch für alle Beteiligten sofort erkennbar wird, um welche Revision es sich handelt.
Noch komfortabler ist die Option -v, die direkt eine Versionsnummer entgegennimmt und sowohl das Präfix als auch die Dateinamen automatisch entsprechend anpasst, ohne dass ein eigener Präfix-Text manuell konstruiert werden muss. So bleibt für jede Revision einer Serie klar nachvollziehbar, welche Version tatsächlich vorliegt.
# Zweite Revision einer Patch-Serie erzeugen, Präfix und Dateinamen automatisch angepasst
git format-patch main -v2 --cover-letter --output-directory patches/
6. Serien miteinander vergleichen mit git range-diff
Wer eine zweite Version einer Patch-Serie prüft, möchte meist wissen, was sich seit der ersten Fassung inhaltlich tatsächlich verändert hat, statt jeden Patch erneut komplett von vorn zu lesen. git range-diff vergleicht dafür zwei Commit-Bereiche inhaltlich miteinander und markiert, welche Patches identisch geblieben sind, welche sich verändert haben und welche neu hinzukamen.
Für Reviewer einer neuen Version ist das der schnellste Weg, um sich ausschließlich auf die tatsächlichen Änderungen gegenüber der vorherigen Fassung zu konzentrieren, statt bei jeder Revision erneut die komplette Serie von Grund auf zu prüfen.
# Erste und zweite Version derselben Serie inhaltlich vergleichen
git range-diff main feature-v1 feature-v2
7. Empfängerseite: Patches prüfen und anwenden
Auf der Empfängerseite genügt für eine einzelne Datei oder ein Verzeichnis meist git am, um die Serie in vollständige Commits mit Original-Autor und Original-Datum zu verwandeln. Vor dem eigentlichen Anwenden lohnt sich häufig ein Blick mit git apply --check, das lediglich prüft, ob ein Patch sauber passen würde, ohne bereits irgendeine Änderung vorzunehmen.
Bei umfangreicheren Serien ist es üblich, die Patches zunächst in einem separaten, lokalen Test-Branch anzuwenden, dort die automatisierte Testsuite laufen zu lassen und erst danach über die Übernahme in den Hauptbranch zu entscheiden, ganz ähnlich wie bei einem Pull-Request-Merge, nur ohne das dazugehörige Web-Interface.
# Vor dem Anwenden prüfen, ob der Patch überhaupt sauber passt
git apply --check 0001-fix-cache-invalidation.patch
# In einem eigenen Test-Branch anwenden, um vor dem Merge zu testen
git checkout -b test-patch-serie main
git am patches/*.patch
8. Wann sich der patch-basierte Workflow gegenüber Pull Requests lohnt
Der patch-basierte Workflow zahlt sich vor allem dort aus, wo kein einzelnes, zentrales Forge alle Beteiligten verbindet, etwa bei Projekten mit mehreren unabhängigen Mirror-Repositories, bei Beiträgen über instabile oder eingeschränkte Internetverbindungen, oder wenn Beitragende aus rechtlichen oder organisatorischen Gründen keinen Account bei einem bestimmten Anbieter anlegen können oder wollen.
Für ein typisches, zentral über GitLab organisiertes Magento- oder Web-Projekt mit einem festen Team ist der Aufwand dagegen selten gerechtfertigt, weil Pull Requests dort Inline-Kommentare, automatische CI-Läufe und eine niedrigere Einstiegshürde für neue Teammitglieder bieten, die ein reiner E-Mail-Workflow nicht ohne Weiteres nachbilden kann.
9. Praktische Stolperfallen und Checkliste für den Einstieg
Die häufigste Fehlerquelle ist ein Mail-Client, der reinen Text automatisch in HTML umwandelt und dabei Zeilenumbrüche oder Einrückungen des Diffs verändert, wodurch der Patch beim Empfänger nicht mehr sauber anwendbar ist. Wer keinen textbasierten Mail-Client oder git send-email verwenden kann, sollte Patches deshalb möglichst als reine Textanhänge versenden, nicht als eingebetteten Nachrichtentext.
Eine weitere häufige Stolperfalle ist eine unklare Reihenfolge bei mehrteiligen Serien: Ohne konsistente Nummerierung und Cover Letter ist für Empfänger oft nicht sofort ersichtlich, in welcher Reihenfolge die Patches angewendet werden müssen. Konsequente Nutzung von --cover-letter und automatischer Nummerierung vermeidet dieses Problem von vornherein zuverlässig.
| Aspekt | Pull Request | format-patch-Workflow | Empfehlung |
|---|---|---|---|
| Zentrale Instanz nötig | Ja, ein Forge wie GitLab | Nein, beliebiger Übertragungsweg | format-patch bei fehlendem Forge |
| Inline-Kommentare im Web | Ja, eingebaut | Nein, nur per E-Mail-Antwort | Pull Request für Web-Review |
| Automatische CI-Läufe | Meist eingebaut | Nur mit zusätzlicher Infrastruktur | Pull Request bei aktivem CI-Bedarf |
| Funktioniert offline vorbereitbar | Eingeschränkt | Ja, vollständig | format-patch bei instabiler Anbindung |
| Versionierung einer Serie | Force-Push auf denselben Branch | Eigene v2, v3 Dateien und Threads | format-patch für nachvollziehbare Historie |
Mironsoft
Git-Workflows, Branching-Strategien und CI-Hooks
Chaotische Git-Historie und unklare Branching-Regeln im Team?
Wir richten saubere Git-Workflows ein, klären Branching-Strategien fürs Team und automatisieren Qualitätschecks über Git-Hooks und CI-Pipelines, damit die Historie nachvollziehbar bleibt.
Workflow-Audit
Bestehende Branching-Strategie und Merge-Praxis auf Schwachstellen prüfen.
Hook-Automatisierung
Pre-Commit- und Pre-Push-Hooks für Linting, Tests und Commit-Konventionen einrichten.
Team-Schulung
Rebase, Cherry-Pick und Konfliktauflösung im Team praxisnah vermitteln.
10. Zusammenfassung
format-patch-Workflow
Grundprinzip
git format-patch wandelt Commits in versendbare Textdateien um, die der Empfänger mit git am wieder zu Commits zusammensetzt.
Serie mit Kontext
Mit --cover-letter entsteht eine zusätzliche Übersichtsdatei, die Motivation und Umfang der gesamten Serie erklärt.
Versand
git send-email verschickt Patches als korrekt formatierte Text-E-Mails, ohne die Zeilenumbrüche des Diffs zu zerstören.
Revisionen vergleichen
git range-diff zeigt inhaltlich, was sich zwischen zwei Versionen einer Serie tatsächlich geändert hat.