wiederkehrende Merge-Konflikte automatisch lösen lassen
Wer einen lang laufenden Feature-Branch regelmäßig gegen main rebased, kennt das Problem: Derselbe Konflikt in derselben Datei taucht bei jedem Rebase erneut auf. git rerere merkt sich die einmal gefundene Lösung und wendet sie beim nächsten identischen Konflikt automatisch wieder an, ganz ohne externes Werkzeug.
Inhaltsverzeichnis
- 1. Was git rerere macht und wofür es gedacht ist
- 2. rerere aktivieren und den Cache verstehen
- 3. Der Workflow bei einem wiederkehrenden Konflikt
- 4. Typische Einsatzszenarien: lange Feature-Branches und Cherry-Pick-Serien
- 5. Den rerere-Cache pflegen: forget, diff und Status prüfen
- 6. Risiken: falsch gelernte Konfliktlösungen automatisch übernehmen
- 7. rerere im Team: warum der Cache meist lokal bleibt
- 8. Den Cache mit einem Trainings-Skript vorab befüllen
- 9. Abgrenzung zu Merge-Strategien und benutzerdefinierten Mergern
- 10. Zusammenfassung
- 11. FAQ
1. Was git rerere macht und wofür es gedacht ist
Rerere steht für reuse recorded resolution, also die Wiederverwendung einer bereits aufgezeichneten Konfliktlösung. Sobald die Funktion aktiviert ist, speichert Git bei jedem manuell gelösten Merge-Konflikt den Zustand vor und nach der Auflösung. Taucht später ein Konflikt mit demselben Vorher-Zustand erneut auf, wendet Git die gespeicherte Lösung automatisch an, ohne dass jemand erneut manuell eingreifen muss.
Das Werkzeug greift bei allen Operationen, die Konflikte erzeugen können, also bei git merge, git rebase und git cherry-pick gleichermaßen. Besonders wertvoll wird das bei wiederholten Vorgängen auf demselben Datenbestand, etwa wenn ein Feature-Branch nach jedem Force-Push von main erneut rebased werden muss und dabei immer wieder an derselben Stelle in einer Konfigurationsdatei hakt.
2. rerere aktivieren und den Cache verstehen
Standardmäßig ist rerere in den meisten Git-Installationen deaktiviert und muss explizit eingeschaltet werden, entweder global für alle Repositories oder gezielt für ein einzelnes Projekt. Sobald aktiv, legt Git seinen internen Speicher unter .git/rr-cache an, ein reines lokales Verzeichnis, das nicht Teil der versionierten Projektdateien ist.
Eine zusätzliche Option ist rerere.autoupdate: Ist sie gesetzt, führt Git nach einer automatisch erkannten Konfliktlösung sofort ein implizites git add für die betroffene Datei aus, sodass kein manueller Zwischenschritt mehr nötig ist, um die Auflösung als erledigt zu markieren.
# rerere global für alle Repositories aktivieren
git config --global rerere.enabled true
# automatisches Stagen erkannter Konfliktlösungen zusätzlich aktivieren
git config --global rerere.autoupdate true
3. Der Workflow bei einem wiederkehrenden Konflikt
Beim ersten Auftreten eines Konflikts läuft alles wie gewohnt ab: Git markiert die betroffenen Stellen mit den bekannten Konfliktmarkern, die Konfliktzeilen werden manuell bereinigt, die Datei wird mit git add als gelöst markiert, und der Merge oder Rebase wird fortgesetzt. Im Hintergrund hat rerere in genau diesem Moment bereits den Vorher-Zustand und die gewählte Lösung im Cache abgelegt.
Taucht exakt derselbe Konfliktinhalt zu einem späteren Zeitpunkt erneut auf, etwa weil derselbe Feature-Branch nach einem weiteren Commit auf main erneut rebased wird, erkennt Git den bereits bekannten Konflikt automatisch, wendet die gespeicherte Lösung an und markiert die betroffene Stelle direkt als aufgelöst, ohne dass die Konfliktmarker überhaupt sichtbar werden.
# Nach einem erkannten, automatisch gelösten Konflikt zeigt Git einen Hinweis
git rebase main
# Resolved 'config/app.yaml' using previous resolution.
4. Typische Einsatzszenarien: lange Feature-Branches und Cherry-Pick-Serien
Der klassische Anwendungsfall ist ein Feature-Branch, der über mehrere Wochen parallel zu main entwickelt und dabei regelmäßig neu rebased wird. Wenn dabei immer wieder dieselbe generierte Datei oder dieselbe zentrale Konfigurationsdatei kollidiert, erspart rerere ab dem zweiten Auftreten jede manuelle Wiederholung derselben Konfliktlösung.
Ein zweites häufiges Szenario sind Cherry-Pick-Serien zwischen mehreren Release-Branches, bei denen dieselben Hotfix-Commits auf unterschiedliche, leicht abweichende Branch-Stände angewendet werden müssen. Sobald der erste Cherry-Pick die passende Konfliktlösung liefert, kann rerere dieselbe Lösung bei den folgenden Branches automatisch übernehmen.
5. Den rerere-Cache pflegen: forget, diff und Status prüfen
Für die Übersicht während eines aktiven Konflikts liefert git rerere status die Liste der Pfade, für die eine gespeicherte Lösung gefunden oder verwendet wurde, während git rerere diff zeigt, welche konkreten Änderungen rerere gerade automatisch anwendet, bevor sie tatsächlich übernommen werden.
Wurde eine automatische Auflösung fälschlicherweise übernommen, entfernt git rerere forget <pfad> die betroffene Aufzeichnung gezielt aus dem Cache, sodass beim nächsten Konflikt wieder eine manuelle Entscheidung nötig ist. Alte, lange nicht mehr benötigte Einträge räumt git rerere gc automatisch nach konfigurierbaren Zeiträumen für gelöste und ungelöste Konflikte auf.
# Aktuellen rerere-Status während eines Konflikts anzeigen
git rerere status
git rerere diff
# Eine falsch gelernte Lösung für einen Pfad verwerfen
git rerere forget config/app.yaml
6. Risiken: falsch gelernte Konfliktlösungen automatisch übernehmen
Der größte Schwachpunkt von rerere ist gleichzeitig seine größte Stärke: Es merkt sich exakt das, was einmal manuell entschieden wurde, und zwar unabhängig davon, ob diese Entscheidung inhaltlich richtig war. War die erste Konfliktlösung fehlerhaft, wendet Git dieselbe fehlerhafte Lösung beim nächsten identischen Konflikt still und ohne Rückfrage erneut an.
Gerade bei sicherheitsrelevantem Code oder komplexer Geschäftslogik lohnt es sich deshalb, nach jeder automatisch angewendeten Lösung noch einmal gezielt mit git diff zu prüfen, was tatsächlich übernommen wurde, statt der Automatik blind zu vertrauen. rerere ersetzt kein Code-Review, es beschleunigt nur die mechanische Wiederholung einer bereits einmal getroffenen Entscheidung.
Ein weiterer Grund für Vorsicht: Wird ein Konflikt beim ersten Mal nur oberflächlich gelöst, etwa weil unter Zeitdruck einfach die eigene Variante übernommen wurde, ohne die inhaltliche Bedeutung der anderen Seite zu prüfen, speichert rerere genau diese oberflächliche Entscheidung dauerhaft ab. Ein kurzer Kommentar im Commit, welche Entscheidung getroffen wurde und warum, hilft späteren Beteiligten, die automatisch wiederholte Lösung im Nachhinein besser einordnen zu können.
7. rerere im Team: warum der Cache meist lokal bleibt
Das Verzeichnis .git/rr-cache liegt außerhalb der normalen Projektdateien und wird standardmäßig nicht mit Commits versioniert, wodurch jede Entwicklerin und jeder Entwickler einen eigenständigen, lokalen Cache aufbaut. Das ist in den meisten Fällen auch sinnvoll, da Konfliktlösungen oft von individuellen lokalen Branch-Ständen abhängen, die zwischen Teammitgliedern variieren.
In Ausnahmefällen, etwa bei einem sehr großen Team, das denselben bekannten Konflikt in einer generierten Datei immer wieder unabhängig voneinander löst, lässt sich der Cache technisch auch über ein eigenes Verteilungsskript teilen, in der Praxis ist das aber die Ausnahme und keine Standardempfehlung.
8. Den Cache mit einem Trainings-Skript vorab befüllen
Im contrib-Verzeichnis der Git-Quellen liegt ein Skript namens rerere-train.sh, das die komplette bestehende Merge-Historie eines Repositories durchgeht, jeden historischen Merge-Commit erneut simuliert und die dabei entstehenden Konfliktlösungen in den lokalen rerere-Cache einspeist.
Das ist besonders nützlich direkt nach dem frischen Klonen eines Repositories, dessen Team bereits bekannte, wiederkehrende Konflikte hat: Statt jeden dieser Konflikte erneut manuell zu lösen, füllt das Trainings-Skript den Cache im Voraus, sodass rerere schon beim ersten eigenen Rebase greifen kann.
# Bestehende Merge-Historie einmalig für rerere trainieren
./rerere-train.sh $(git rev-list --all --merges)
9. Abgrenzung zu Merge-Strategien und benutzerdefinierten Mergern
rerere ersetzt keine inhaltlichen Merge-Strategien wie einen merge=union-Treiber in .gitattributes, der für bestimmte Dateitypen von vornherein definiert, wie Änderungen automatisch zusammengeführt werden sollen. Ein solcher Treiber wendet eine allgemeine Regel an, bevor überhaupt ein Konflikt entsteht.
rerere setzt dagegen erst an, nachdem ein Konflikt tatsächlich aufgetreten und einmal manuell gelöst wurde, und wiederholt danach exakt diese konkrete, bereits getroffene Entscheidung. Beide Mechanismen ergänzen sich gut: Ein Merge-Treiber deckt vorhersehbare, generische Fälle ab, rerere übernimmt die individuellen, wiederkehrenden Konflikte, die sich nicht pauschal per Regel lösen lassen.
| Merkmal | git rerere | merge=union Treiber | Manuelles Wiederholen |
|---|---|---|---|
| Wirkt vor oder nach dem Konflikt | Nach dem ersten manuellen Lösen | Vor dem Entstehen des Konflikts | Bei jedem Auftreten erneut |
| Speicherort der Lösung | Lokaler Cache unter .git/rr-cache | Regel in .gitattributes, versioniert | Nirgends, jedes Mal neu |
| Geeignet für individuelle Konflikte | Ja, exakte Vorher-Nachher-Zustände | Nein, nur generische Regeln | Ja, aber zeitaufwendig |
| Automatisierungsgrad | Hoch, nach dem ersten Mal automatisch | Hoch, aber nur regelbasiert | Keiner |
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
Git Rerere
Kernidee
git rerere merkt sich eine einmal manuell gefundene Konfliktlösung und wendet sie bei identischen Konflikten automatisch erneut an.
Aktivierung
git config rerere.enabled true schaltet den Mechanismus ein, der Cache liegt lokal unter .git/rr-cache.
Typischer Einsatz
Lang laufende Feature-Branches mit wiederholtem Rebase und Cherry-Pick-Serien über mehrere Release-Branches.
Wichtige Regel
Automatisch angewendete Lösungen dennoch per git diff prüfen, rerere wiederholt auch eine ursprünglich falsche Entscheidung.