Files
management/docs/adr/0022-upstream-anschluss-durch-einmaligen-merge.md
Thore Cimbal 6731d2a70f ADR-0023: fremde Historie erklaert von der Git-Hygiene ausnehmen
Der Upstream-Merge holte 70.265 fremde Commits nach ThreadNet-Web; 39 davon
faerbten die Gruppenpruefung als Echtzeit-Stempel rot. Sie verletzen die
Konvention wirklich, konnten ihr aber nie folgen und werden sich nie aendern -
also ein Dauerrot, und ein Dauerrot meldet nichts mehr (#0104).

Neues Feld fremdhistorie in docs/components/*.md. Wo gesetzt, prueft die
Hygiene nur Commits, die von eigenen Identitaeten COMMITTET wurden. Der
Trennschnitt ist gemessen, nicht geraten: 18 eigene Commits, alle von uns
committet; 39 fremde von GitHub/RiotRobot; keine Ueberschneidung. Der Autor
taugt nicht - eigene Commits koennen fremde Autoren tragen (Cherry-Picks).

Der Feldwert ist die Begruendung, kein Schalter - Muster der Quittungen aus
ADR-0020. Die Ausnahme gilt nur, wo sie deklariert ist, nicht global; der Preis
(ein Commit unter voellig unbekannter Identitaet faellt dort durchs Raster)
steht in den Konsequenzen.

Belegt: nach dem Fix 0 offene Befunde bei 20 Quittungen, und in ThreadNet-Web
werden weiterhin 18 Commits geprueft, alle auf 12:00:00.

Ausserdem zurueckgenommen: mein Nachtrag an ADR-0022. Eine angenommene ADR wird
nicht editiert (Regel in der Vorlage) - die Erkenntnis steht jetzt in #0099.
2026-08-19 12:00:00 +00:00

3.5 KiB

type, id, status, date, supersedes, superseded_by, related
type id status date supersedes superseded_by related
adr 0022 accepted 2026-08-19 null null
docs/issues/0099-threadnet-web-12-upstream-sicherheitsfixes-lassen-sich-nicht-m.md

ADR-0022: Anschluss an Upstream durch einen einmaligen Merge, nicht durch einen geteilten Graft

Kontext

ThreadNet-Web enthält keine Upstream-Historie: Am 2026-05-10 kam ein kompletter Element-Web-Baum in einem Commit herein. Ohne gemeinsamen Vorfahren ist git merge upstream/develop unmöglich, und jedes Update bedeutet, zwölf eigene Patches von Hand auf einen neuen Baum aufzutragen. Das ist nicht nur mühsam, sondern gefährlich: Verschiebt Element eine Datei, verschwinden unsere Zeilen ohne Konflikt (#0099).

Am 2026-08-19 wurde der tatsächliche Ursprung gemessen statt geraten: deadd548 vom 2026-05-08 (nicht der Tag v1.12.17, wie zuvor angenommen). Der Beleg ist die Baumdistanz — 43 abweichende Dateien, davon 31 reine Modus-Änderungen und der Rest unser eigenes Feature.

Im Wegwerf-Klon getestet: Mit gesetztem Vorfahren läuft ein Merge von drei Monaten develop durch und erzeugt 32 konfliktbehaftete Dateien, davon nur vier Quellcode — genau unsere Patches.

Optionen

A: Geteilter Replace-Ref. git replace --graft und refs/replace/* mitliefern. Die Historie bleibt formal unverändert, Git interpretiert sie nur anders. Nachteil: Jeder Klon braucht einen zusätzlichen Fetch, und wer ihn vergisst, sieht eine andere Historie als alle anderen — ein stiller Unterschied, der sich erst im Konfliktfall zeigt.

B: Einmaliger echter Merge, danach normale Merges.

⚠️ Praezisierung nach dem Test: --allow-unrelated-histories allein liefert einen ZWEI-Wege-Vergleich und damit 1757 Konflikte — gemessen. Der Graft ist kein Gegenentwurf zu B, sondern sein Werkzeug: lokal setzen, den Merge damit rechnen lassen (32 Konflikte), committen. Der Merge-Commit traegt danach die echten Eltern, der Graft kann weg, und die Abstammung laeuft ueber den Merge-Commit selbst. Die Nahtstelle wird ein sichtbarer Merge-Commit. Kein Sonderwissen, kein Zusatzschritt, kein Klon kann sie versehentlich übersehen.

C: So weiterarbeiten wie bisher — Patches von Hand auftragen. Verworfen: Das ist der Zustand, der die stille Klasse überhaupt erst erzeugt.

Entscheidung

Option B (sorb, 2026-08-19).

Ausschlaggebend ist nicht der Aufwand — beide Wege sind ähnlich billig — sondern die Sichtbarkeit. A funktioniert nur, solange alle daran denken; B trägt sich selbst. Für ein Repo, dessen Kernproblem „Git meldet nichts" ist, wäre ein Mechanismus, der stillschweigend unterschiedlich wirkt, die falsche Wahl.

deadd548 bleibt trotzdem wichtig: Es ist der Stand, gegen den der Merge gefahren wird, und ohne diese Messung wäre der Merge auf eine erfundene Grundlage gelaufen.

Konsequenzen

  • Der erste Merge ist ein einmaliger Kraftakt mit vier Quellcode-Konflikten; danach ist ein Upstream-Update ein gewöhnlicher Merge.
  • Die stille Klasse verschwindet: Verschiebt Upstream eine Datei, die wir angefasst haben, meldet Git künftig einen Konflikt, statt unsere Zeilen wortlos fallen zu lassen.
  • Die Nahtstelle bleibt als Merge-Commit dauerhaft sichtbar — gewollt, nicht geduldet.
  • Abnahme ist kein Build, sondern ein Funktionstest: Die ClamAV-Patches liegen in der Medien-Pipeline. Ohne den Test aus #0099 (verschlüsselte Datei senden, abgelehnte empfangen) ist der Merge nicht abgenommen.
  • Schritt 4 aus #0099 — ein Verfahren zum Auftragen der Patches — wird damit gegenstandslos.