Betere Git-commitberichten schrijven met consistente hoofdletters

Een goed Git-commitbericht heeft een korte onderwerpregel (mik op 50 tekens) in de gebiedende wijs, in het Engels ‘Add’ in plaats van ‘Added’, en zonder punt aan het eind. Daarna volgt een lege regel en dan een body die op 72 tekens is afgebroken en uitlegt waarom de wijziging is gemaakt. Kies voor hoofdletters één conventie en houd je eraan: met een voorvoegsel als feat: of docs: begint het woord erna meestal met een kleine letter; zonder voorvoegsel is het klassieke advies om het eerste woord met een hoofdletter te schrijven.
Git zelf dwingt hier niets van af, en daarom lopen historieken uit de pas. Hieronder staan de regels, waar elke regel vandaan komt en hoe je ze door je tools laat controleren, zodat je ze niet hoeft te onthouden.
De opbouw van een goed commitbericht
fix(editor): keep cursor position after paste
Pasting into an empty textarea moved the cursor to the start, because
the change handler replaced the value before restoring the selection.
Restore the selection after updating the value instead.
Fixes #142Drie delen: een onderwerp dat zegt wat de commit doet, een body die zegt waarom, en optionele footers voor verwijzingen en metadata. De eigen documentatie van Git raadt aan te beginnen met “a single short (no more than 50 characters) line summarizing the change, followed by a blank line and then a more thorough description” (één korte regel van maximaal 50 tekens die de wijziging samenvat, gevolgd door een lege regel en dan een uitgebreidere beschrijving). Alles tot de eerste lege regel geldt als de titel van de commit, en dat is wat git log --oneline, git shortlog en git format-patch laten zien.
De onderwerpregel: kort, in de gebiedende wijs, zonder punt
Vijftig tekens is een zachte grens. De eigen SubmittingPatches-gids van het Git-project noemt het precies zo en vraagt bijdragers om “skip the full stop” (de punt weg te laten). Kom je niet onder de 50, dan is dat vaak een teken dat de commit twee dingen doet.
Dezelfde gids vraagt je om “describe your changes in imperative mood” (beschrijf je wijzigingen in de gebiedende wijs), alsof je bevelen geeft aan de codebase: “make xyzzy do frotz”, niet “makes xyzzy do frotz” of “changed xyzzy to do frotz”. Een handige test uit de zeven regels voor commitberichten van Chris Beams: een goede onderwerpregel maakt de zin “If applied, this commit will …” (als dit wordt toegepast, zal deze commit …) af.
- “If applied, this commit will add CSV export” werkt.
- “If applied, this commit will added CSV export” werkt niet.
- “If applied, this commit will bug fixes” werkt ook niet en zegt de lezer niets.
De gebiedende wijs past ook bij de berichten die Git zelf voor je schrijft, zoals Merge branch 'main' en Revert "…", zodat je eigen commits in de log hetzelfde lezen.
Hoofdletters in de onderwerpregel: de twee kampen
Hier spreken adviezen elkaar echt tegen, en het juiste antwoord hangt ervan af of je onderwerpregels met een voorvoegsel beginnen.
| Conventie | Voorbeeld | Wie het aanbeveelt |
|---|---|---|
| Geen voorvoegsel, met hoofdletter | Add CSV export | Tim Popes notitie over commitberichten uit 2008; de zeven regels van Chris Beams |
| Voorvoegsel voor het gebied, daarna een kleine letter | doc: clarify sign-off rules | SubmittingPatches van het Git-project |
| Voorvoegsel voor het type, beschrijving met een kleine letter | feat: add CSV export | De commitrichtlijnen van Angular; de conventional-configuratie van commitlint |
De versie van het Git-project heeft een detail dat het kopiëren waard is. Alleen het eerste woord na het voorvoegsel verliest zijn hoofdletter, en alleen omdat het het eerste woord is: woorden die altijd met een hoofdletter worden geschreven, houden die. Het eigen voorbeeld is refs: HEAD is also treated as a ref, want HEAD wordt altijd in hoofdletters geschreven. Dezelfde logica geeft fix: handle iOS paste en docs: update README badges.
Ons standpunt: met een voorvoegsel schrijf je het eerste woord met een kleine letter, tenzij het een naam of afkorting is. Zonder voorvoegsel geef je het een hoofdletter. Beide stijlen door elkaar gebruiken is de enige echte fout, want git log --oneline maakt van je onderwerpregels een lijst, en een lijst die om de paar regels van hoofdletterstijl wisselt, ziet er slordig uit. Dezelfde redenering toegepast op documentatie vind je in onze gids over consistente documentatie schrijven.
Wat de specificatie van Conventional Commits echt zegt
De specificatie Conventional Commits 1.0.0 definieert deze structuur:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]De belangrijkste regels, kort:
feat(een nieuwe functie) enfix(een bugfix) zijn de twee typen die de specificatie definieert, en ze komen overeen met MINOR- en PATCH-releases in Semantic Versioning, waarbij breaking changes op MAJOR uitkomen. Andere typen zijn toegestaan; de specificatie noemtbuild,chore,ci,docs,style,refactor,perfentest, zoals aanbevolen door de conventional-configuratie van commitlint, die op de conventie van Angular is gebaseerd.- Een breaking change markeer je met
!voor de dubbele punt (feat!: drop Node 16 support) of met een footerBREAKING CHANGE:, en die footer moet in hoofdletters staan. - Tools die het formaat lezen, mogen het niet hoofdlettergevoelig behandelen, behalve
BREAKING CHANGE. Over de vraag of typen met kleine letters of met hoofdletters moeten worden geschreven, zegt de FAQ van de specificatie dat elke schrijfwijze mag, “but it's best to be consistent” (maar het is het beste om consistent te zijn).
De specificatie schrijft geen lengte van de onderwerpregel voor en eist de gebiedende wijs niet. Die komen uit de Git-conventie.
Waar commitlint strenger is dan de specificatie
De @commitlint/config-conventional van commitlint is de gebruikelijke manier om het formaat af te dwingen, en de standaardregels gaan verder dan de specificatie. We hebben voorbeeldonderwerpen door versie 21 gehaald:
| Onderwerpregel | Resultaat |
|---|---|
feat: add CSV export | Geslaagd |
feat: Add CSV export | Mislukt: onderwerp mag niet in Zinsvorm (sentence case) staan |
Feat: add CSV export | Mislukt: type moet uit kleine letters bestaan |
fix: handle empty textarea. | Mislukt: geen punt toegestaan |
fix: README typo | Mislukt: telt ook als Zinsvorm |
fix: typo in README | Geslaagd |
Let vooral op de README-rij. Een onderwerpregel die met een afkorting of een klassenaam begint, zoals fix: README typo of feat: URLSearchParams support, wordt afgewezen, ook al zou het Git-project het equivalent accepteren. Herformuleer zodat de afkorting niet vooraan staat, of versoepel de regel subject-case in je configuratie. De standaardlimiet voor de header is 100 tekens, dus commitlint houdt je ook niet aan 50.
De body: breek af op 72 en leg uit waarom
Git breekt je bericht nooit zelf af. De uitleg van Tim Pope uit 2008 geldt nog steeds: git log laat berichten vier spaties inspringen, dus op een terminal van 80 kolommen blijven er 72 kolommen over als je rechts ook vier vrijhoudt voor de symmetrie, en afgebroken tekst blijft ook leesbaar als commits met git format-patch worden gemaild. Onze tool Tekst afbreken op N tekens breekt een alinea op woordgrenzen af op 72 tekens als je editor dat niet doet.
Gebruik de body voor wat de diff niet kan laten zien: het probleem, waarom juist deze oplossing, en alles wat je hebt geprobeerd dat niet werkte. Vanaf de opdrachtregel wordt elke -m een eigen alinea, dus git commit -m "fix: keep cursor after paste" -m "Pasting into…" levert een onderwerp, een lege regel en een body op.
Laat je tools het controleren
- VS Code: zet
"git.inputValidation": true. Het commitvak waarschuwt dan als het onderwerp over de 50 tekens gaat (git.inputValidationSubjectLength) of een andere regel over de 72 (git.inputValidationLength). - Vim: de meegeleverde instellingen voor commitberichten breken de body af op 72 (
textwidth=72) en stoppen na 50 tekens met het markeren van het onderwerp. - Een commitsjabloon:
git config commit.template ~/.gitmessagelaat elke commit in de editor beginnen met je geheugensteuntjes. - Een commit-msg-hook voor controles zonder afhankelijkheden. Sla dit op als
.git/hooks/commit-msgen maak het uitvoerbaar:
#!/bin/sh
# Checks the subject line of every commit message.
subject=$(head -n 1 "$1")
length=${#subject} # counts bytes in some shells; fine for ASCII subjects
if [ "$length" -gt 72 ]; then
echo "commit-msg: subject is $length characters (limit 72, aim for 50)" >&2
exit 1
fi
if [ "$length" -gt 50 ]; then
echo "commit-msg: note, subject is $length characters (aim for 50)" >&2
fi
case "$subject" in
*.) echo "commit-msg: drop the full stop at the end of the subject" >&2
exit 1 ;;
esac
if [ -n "$(sed -n 2p "$1")" ]; then
echo "commit-msg: leave line 2 blank, between subject and body" >&2
exit 1
fiHet script waarschuwt boven de 50 tekens en weigert onderwerpen van meer dan 72 tekens, een punt aan het eind of een ontbrekende lege regel, en met git commit --no-verify sla je het over als het echt nodig is. Voor een snelle telling voordat je commit, plak je het onderwerp in onze Tekenteller.
De checklist dus: een onderwerpregel in de gebiedende wijs van ongeveer 50 tekens, zonder punt, één hoofdletterregel voor de hele repository, een lege regel, een body op 72 tekens die uitlegt waarom, en een hook of linter zodat de regels een drukke week overleven.


