From: Kai Moritz Date: Sat, 13 Jun 2026 11:56:23 +0000 (+0000) Subject: docs: Halbautomatischen Rebase-Workflow und Kaskaden-Konfliktmuster dokumentiert X-Git-Url: http://juplo.de/gitweb/?a=commitdiff_plain;h=fc740d012ab920f2326bf89468f763e94d92ebe9;p=demos%2Fkafka%2Ftraining docs: Halbautomatischen Rebase-Workflow und Kaskaden-Konfliktmuster dokumentiert Ergänzt den Workflow für rebase.sh-gestützte Massen-Rebases sowie die drei neuen Konfliktmuster, die in der Praxis regelmäßig auftreten: - Duplikat-Commits durch Hash-Verschiebung (Kaskaden-Problem) - Modify/Delete-Konflikte in reinen Infrastruktur-Branches - Konflikte durch Erweiterungen im ROOT-Branch Co-Authored-By: Claude Sonnet 4.6 --- diff --git a/CLAUDE.md b/CLAUDE.md index 2abefdf7..f319b6db 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -318,6 +318,21 @@ In diesen Fällen: Problem zeigen, erklären warum es wichtig ist, und einen kon - Verbesserungen von späteren auf frühere Branches zurückportieren, wo sinnvoll - Nach dem Rebasen immer zum `scripting`-Branch zurückkehren +### Halbautomatischer Workflow mit `rebase.sh` + +Für vollständige Rebases über alle Branches wird `rebase.sh` eingesetzt. Das Skript iteriert alle Branches in der richtigen Reihenfolge (ROOT-Branches zuerst) und rebasiert sie nicht-interaktiv. Bei Konflikten bricht es ab. + +**Workflow:** + +1. `./rebase.sh` starten. +2. Bricht das Skript bei einem Branch ab, gilt es zu untersuchen, woran es liegt: + + **Fall A – Duplikat-Commit:** Der scheiternde Commit findet sich bereits mit exakt gleichem Namen im `git log `. Ursache: Ein Commit wurde in einem vorgelagerten Rebase inhaltlich verändert, sein Hash hat sich dadurch geändert, und git erkennt ihn nicht mehr als „bereits enthalten". → Lösung: Duplikat per interaktivem Rebase mit `drop` entfernen (siehe Konfliktmuster „Duplikat-Commits durch Hash-Verschiebung"). + + **Fall B – Echter Inhaltskonflikt:** Der scheiternde Commit ist im ROOT-Branch nicht enthalten. → Konflikt manuell auflösen (siehe Wiederkehrende Konfliktmuster), dann `git rebase --continue`. + +3. Nach der Auflösung: `git checkout scripting` (das Skript lässt den Branch ausgecheckt — `lib.sh` und `rebase.sh` sind nur auf `scripting` sichtbar) und `./rebase.sh` neu starten. Es läuft über bereits erledigte Branches ohne Aktion hinweg und setzt beim nächsten Problem an. + ## Live-Codings Live-Codings verbinden die technischen Lücken zwischen den Übungsgruppen. Jedes Live-Coding zeigt schrittweise die Unterschiede zwischen dem Setup (und den benötigten "off-topic"-Techniken und Boilerplate-Code) in einem gegebenen Ausgangsbranch und einem neuen Zielbranch für die kommenden Übungen. @@ -441,6 +456,45 @@ Aus dem eingehenden Commit wiederherstellen: `git checkout `. + +Lösung per `GIT_SEQUENCE_EDITOR`: +```bash +# 1. Einmalig pro Session erstellen; alte Hashes nach Bedarf ergänzen: +cat > /tmp/drop_duplicates.sh << 'EOF' +#!/bin/bash +sed -i '/alter_hash_1\|alter_hash_2/d' "$1" +EOF +chmod +x /tmp/drop_duplicates.sh + +# 2. Duplikat aus dem Branch entfernen (7+ Zeichen des alten Hash genügen): +GIT_SEQUENCE_EDITOR=/tmp/drop_duplicates.sh git rebase -i +``` + +**Kaskadierung:** Wenn der Rebase von Branch P einen Commit inhaltlich verändert, müssen alle Kinder-Branches von P den alten Hash droppen. Haben diese Kinder-Branches ihrerseits branch-spezifische Commits (z.B. Versions-Commit), die durch ihren Rebase ebenfalls verändert werden, müssen deren alte Hashes für die Enkel-Branches ebenfalls in den Filter. Den Filter in `/tmp/drop_duplicates.sh` mit wachsender Tiefe des Baums erweitern. Falls nach dem Drop weitere Konflikte auftreten (meist Versions-Konflikte in `pom.xml`/`build.gradle`): Python-Einzeiler aus dem Versions-Konflikt-Muster oben anwenden, dann `git rebase --continue`. + +**Modify/Delete-Konflikte (reine Infrastruktur-Branches):** +Löscht ein eingehender Commit eine Datei, die HEAD noch (modifiziert) enthält — z.B. wenn ein Branch die Java-Codebasis vollständig durch Docker-only-Setup ersetzt: +```bash +git rm +git rebase --continue +``` + +**Konflikte durch Erweiterungen im ROOT-Branch:** +Wenn eine neue Funktion in einem ROOT-Branch eingeführt wird (z.B. `ConsumerRebalanceListener` in `grundlagen/simple-consumer`), die ein Downstream-Branch bewusst nicht enthält, kann der erste einzigartige Commit des Downstream-Branches konfligieren: HEAD enthält die neue Funktion, aber der Commit wurde gegen die alte Basis ohne sie geschrieben. + +Auflösung: Das Ziel des Downstream-Branches bestimmt die Lösung. Den korrekten Endzustand aus dem (noch nicht rebasiserten) Original-Branch holen: +```bash +git show :src/.../Datei.java > src/.../Datei.java +git add src/.../Datei.java +git rebase --continue +``` +Für `--livecoding--schritte`-Branches: `git checkout --theirs -- ` (nimmt die Version des eingehenden Commits) ist oft die richtige Wahl, um den Schritt so zu reformulieren, dass er im neuen Kontext den richtigen Übergang demonstriert. + ### Bibliotheks-Branches Wandelt ein Branch die Anwendung in eine **reine Java-Bibliothek** um (keine Spring-Boot-App, z.B. `sumup-messages--vorlage`), ist die gesamte Spring-Boot-Deployment-Infrastruktur aus den Build-Dateien zu entfernen: