You are currently rebasing branch 'feature/checkout-summary' onto '4a1c9de'. Sechs Commits, drei davon heißen „fix“, einer heißt „.“, und ich sitze seit vierzig Minuten an einem Konflikt in einer Datei mit 900 Zeilen, die niemand liest.
Ich wollte aufräumen. Sechs Commits zu zwei machen, weil der Reviewer geschrieben hat: „Kannst du das squashen, die Historie ist unlesbar.“ Er hatte recht. Ich hatte drei Commits, die „fix“ hießen, und keinen davon konnte ich heute noch erklären.
Was folgte, war eine Stunde Git, in der ich mehr über meine eigenen Entscheidungen gelernt habe als in sechs Monaten Code-Review. Nicht weil Git klug ist, sondern weil es mich gezwungen hat, sie zu beschreiben.
Sechs Commits, drei davon „fix“
| Commit | Nachricht | Was wirklich drin war |
|---|---|---|
| 1a2b3c4 | feat(checkout): Zusammenfassung als Komponente | die halbe Komponente, ohne Styles |
| 5d6e7f8 | fix | ein Tippfehler in einem Klassennamen |
| 9a0b1c2 | fix | der Fokus-Ring, den ich vergessen hatte |
| 3d4e5f6 | . | Innenabstände von 8 auf 12 px |
| 7c8d9e0 | test: Snapshot für Summary | der Snapshot und ein gelöschter console.log |
| 2f3a4b5 | fix | der eigentliche Bug: eine Zeile im Preisformat |
Vier von sechs Commits sind Nachrichten an niemanden. Der letzte ist der einzige, bei dem ich heute noch wüsste, warum er existiert — und ausgerechnet der heißt „fix“.
Der Konflikt war in einer Zeile, die niemand liest

Die Datei ist ein globales Stylesheet, 900 Zeilen, gewachsen seit 2021, mit einem Abschnitt, der „legacy“ heißt und den niemand mehr anfasst. In Zeile 612 haben beide Seiten eine Regel für .summary__row ergänzt. Meine sagt gap: 8px. Die auf main sagt gap: 12px.
Der Konflikt war nicht technisch. Er war eine Frage: 8 oder 12? Und ich wusste es nicht, weil ich die Entscheidung vor drei Wochen getroffen hatte, ohne sie aufzuschreiben. Also habe ich in den Commit geschaut, und die Nachricht war „fix“, ohne Körper, ohne Grund, ohne Screenshot.
Ich habe 12 genommen, weil main neuer war. Das ist keine Entscheidung, das ist eine Münze mit einem Merge-Konflikt davor. Drei Tage später hat jemand gemerkt, dass die Zeilen in der Zusammenfassung jetzt zu weit auseinanderstehen, und ich musste den Grund rekonstruieren, den ich drei Wochen vorher nicht aufgeschrieben hatte.
Die To-do-Liste
git rebase -i HEAD~6
pick 1a2b3c4 feat(checkout): Zusammenfassung als Komponente
fixup 5d6e7f8 fix
fixup 9a0b1c2 fix
squash 3d4e5f6 .
reword 7c8d9e0 test: Snapshot für Summary
drop 2f3a4b5 fix
Der Unterschied zwischen fixup und squash ist der Unterschied zwischen „weg damit“ und „erzähl mir, was du wolltest“. fixup wirft die Nachricht weg und behält den Inhalt. squash behält beides und öffnet einen Editor, in dem du aus zwei Nachrichten eine machst.
Für die drei „fix“-Commits war fixup richtig, weil es nichts zu erzählen gab. Für 3d4e5f6 war squash richtig, weil die Änderung der Innenabstände eine Entscheidung war, und Entscheidungen brauchen einen Satz.
Und drop für den letzten: Der Bugfix war schon in einem anderen Branch, gemerged, mit einem eigenen Test. Ihn hier zu behalten hätte bedeutet, ihn zweimal zu haben, und beim nächsten Rebase hätte ich mich gefragt, welcher von beiden der richtige ist.
Was mir außerdem geholfen hat, ist unspektakulär: ein Branch vor dem Rebase. git branch backup-vor-rebase kostet eine Sekunde und nimmt dir die Angst, die dich dazu bringt, einen Konflikt falsch aufzulösen, nur um fertig zu werden. Ich habe ihn nicht gebraucht. Ich habe trotzdem besser entschieden, weil er da war.
Was ich über Commit-Nachrichten gelernt habe
Eine Commit-Nachricht ist eine Nachricht an dich selbst in drei Wochen, in einem Zustand, in dem du dich nicht erinnerst. „fix“ ist eine Nachricht an niemanden. Sie kostet drei Sekunden und spart beim nächsten Konflikt nichts, weil sie nichts enthält, was man gegeneinander abwägen könnte.
Drei Regeln, die ich seitdem benutze. Erstens: Schreib das Warum, nicht das Was — das Was steht im Diff. Zweitens: Ein Commit, eine Entscheidung; wenn du „und“ in die Nachricht schreibst, sind es zwei Commits. Drittens: Wenn du einen Konflikt auflöst, schreib die Entscheidung in den Commit, der sie enthält, auch wenn sie banal ist. Besonders dann.
Der Reviewer hat übrigens nichts davon gesehen. Er hat zwei Commits gesehen, beide mit gutem Text, und „sieht gut aus“ geschrieben. Die Stunde Arbeit war unsichtbar, und das ist der Teil an Git, den ich mag und hasse: Es belohnt die Arbeit, die niemand sieht, mit einer Historie, die jeder lesen kann.
Fazit
Rebase ist kein Aufräumen. Es ist Nacherzählen, und Nacherzählen zwingt dich, dich zu erinnern, warum du etwas getan hast. Wenn du es nicht mehr weißt, ist das kein Git-Problem.
Ich rebase seitdem alle zwei Tage, nicht alle zwei Wochen. Nicht wegen der Historie. Weil der Abstand zwischen der Entscheidung und der Erzählung dann kurz genug ist, dass die Erzählung stimmt.
Wenn du in drei Wochen auf deinen letzten Commit schaust: Weißt du noch, warum — oder nur was?
Comments (0)