Arbeitsschloss: der Haken bleibt auf LF, und ein Messfehler von mir

ZWEI NACHTRAEGE ZUM SCHLOSS.

1. DER HAKEN HAT KEINE DATEIENDUNG

Damit greift keine der Regeln in .gitattributes von sich aus — und
git kuendigt beim Committen selbst an: „LF will be replaced by CRLF
the next time Git touches it". Auf Linux ist `#!/bin/sh` mit einem CR
dahinter ein Programmname mit einem unsichtbaren Zeichen am Ende
(„bad interpreter"), und die Datei hat schon einen Kommentar genau
darueber.

Eigene Zeile dazu: `tools/git-haken/* text eol=lf`.

NACHGEMESSEN, DAMIT HIER KEINE BEHAUPTUNG STEHT: Auf Windows
blockiert auch ein CRLF-Haken richtig — Rueckgabe 1, null Commits,
richtige Meldung. Das ist also Vorsorge und keine Reparatur. Aber ein
Haken, der still nicht laeuft, ist genau die Sicherung, die aussieht,
als waere sie da.

Zwei neue Pruefungen dazu: der Haken hat reine LF-Enden (byteweise
gemessen), und die Regel steht in .gitattributes.

2. EIN MESSFEHLER VON MIR, UND ER GEHOERT AUFGESCHRIEBEN

Ich habe gemeldet, im Verlauf lägen 73 CR-Bytes. Es war keines.
Gemessen hatte ich mit einer Rohrkette aus `tr` und `od`, und `tr`
nimmt in dieser Shell die Maskierung fuer das Wagenruecklauf-Zeichen
nicht als Zeichen — gezaehlt wurden am Ende Zeilenenden, und die
Datei hat 73.

Mit Python byteweise nachgemessen: 0 im Arbeitsbaum, 0 im Index. Die
Datei war immer LF; git hat nur VORHERGESAGT, was beim naechsten
Auschecken passiert.

Das ist heute der dritte Messfehler aus Shell-Maskierung — nach zwei
`\b`, die als Steuerzeichen in regulaeren Ausdruecken landeten und
dort je eine Pruefung lahmgelegt haben. Und beim Aufschreiben dieser
Lehre ist sie mir ein viertes Mal passiert: Aus dem Kommentar
`tr -d '\r'` wurde `tr -d ''`, die Aussage hat sich selbst bewiesen
und dabei unlesbar gemacht.

DIE REGEL STEHT JETZT, und zwar im Werkzeug selbst: Alles mit einem
Rueckstrich gehoert in eine DATEI, nie in ein Hier-Dokument. Und wer
Bytes zaehlen will, zaehlt Bytes — `readFileSync` ohne Zeichensatz,
und 13 ist 13.

GEPRUEFT: pruef-arbeitsschloss 33 -> 35 Pruefungen, 0 Fehler.
Steuerzeichen im ganzen Haus: 834 Dateien, keines.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-10-01 20:07:20 +02:00
co-authored by Claude Opus 5
parent 603319a145
commit ec0ee61691
2 changed files with 44 additions and 0 deletions
+11
View File
@@ -26,3 +26,14 @@
*.woff binary
*.woff2 binary
*.conf text eol=lf
# Die git-Haken haben KEINE Endung -- keine der Regeln oben greift auf
# sie. Nachgemessen am 01.10.2026: Im Verlauf lagen 73 CR-Bytes in
# tools/git-haken/pre-commit.
#
# Auf Windows blockiert der Haken damit trotzdem richtig (gemessen:
# Rueckgabe 1, 0 Commits) -- auf Linux nicht, dort ist "#!/bin/sh␍"
# ein Programmname mit einem unsichtbaren Zeichen am Ende. Das ist
# Vorsorge, keine Reparatur: Ein Haken, der still nicht laeuft, ist
# genau die Sicherung, die aussieht, als waere sie da.
tools/git-haken/* text eol=lf
+33
View File
@@ -64,6 +64,39 @@ ok(existsSync(HAKEN), "tools/git-haken/pre-commit ist da");
".arbeitsschloss steht in .gitignore (sonst waere es ein Schloss von gestern)");
}
/* ==== DER HAKEN BRAUCHT LINUX-ZEILENENDEN =========================
Er hat KEINE Dateiendung, also greift keine der Regeln in
.gitattributes von sich aus. Ohne eine eigene Zeile dort wandelt
git ihn beim Auschecken auf Windows in CRLF -- und auf Linux ist
`#!/bin/sh` mit einem CR dahinter ein Programmname mit einem
unsichtbaren Zeichen am Ende („bad interpreter").
NACHGEMESSEN AM 01.10.2026, damit hier keine Behauptung steht:
Auf Windows blockiert auch ein CRLF-Haken richtig (Rueckgabe 1,
null Commits). Die Regel ist also Vorsorge und keine Reparatur --
aber ein Haken, der still nicht laeuft, ist genau die Sicherung,
die aussieht, als waere sie da.
UND EINE LEHRE AUS DEM MESSEN SELBST: Meine erste Messung
meldete 73 CR-Bytes, wo keines war. Gemessen hatte ich mit
einer Rohrkette aus `tr` und `od`, und `tr` nimmt in dieser
Shell die Maskierung fuer das Wagenruecklauf-Zeichen nicht als
Zeichen -- gezaehlt wurden am Ende Zeilenenden.
Byteweise wird deshalb hier gemessen, nicht in einer
Rohrkette: `readFileSync` ohne Zeichensatz gibt Bytes, und
13 ist 13.
*/
{
const roh = readFileSync(HAKEN);
ok(!roh.includes(13),
`der Haken hat reine LF-Zeilenenden (${roh.filter((b) => b === 13).length} CR)`);
const regeln = readFileSync(join(WURZEL, ".gitattributes"), "utf8");
ok(/tools\/git-haken\/\*\s+text\s+eol=lf/.test(regeln),
".gitattributes haelt den Haken auf LF (er hat keine Endung)");
}
/* DER HAKEN MUSS AUCH GEFUNDEN WERDEN. `.git/hooks` wird nicht
versioniert; ohne `core.hooksPath` liegt der Haken im Baum und tut
nichts. Das ist die Sorte Sicherung, die aussieht, als wäre sie da. */