Rexact
Cheatsheet

Regex Conventional Commits message

A Conventional Commits message isn't just "type: description": the official spec itself publishes no regex, only a prose description - and introduces the "!" notation to flag a breaking change ("feat!: ..."), absent from the original Angular convention. The regex used by default by commitlint and semantic-release (inherited from Angular) doesn't handle that "!": a commit that's perfectly valid under spec v1.0.0 fails it. Here's a pattern covering that notation, compared against this widely-used default regex and two other attempts.

/^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\([\w-]+\))?!?: .+$/
passes 21/21 cases

Comparison of existing patterns

Implementation

const re = new RegExp("^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\\([\\w-]+\\))?!?: .+$", "");
re.test(input);

Limits

  • Valide seulement la première LIGNE (le « header ») du message, conformément à la spec : le corps et le pied de page (BREAKING CHANGE, références de tickets) suivent des règles de mise en forme séparées (ligne vide obligatoire avant le corps) qu'une regex sur une seule ligne ne peut pas vérifier.
  • La liste de types utilisée ici (build/chore/ci/docs/feat/fix/perf/refactor/revert/style/test) vient de la convention Angular, largement adoptée mais non imposée par la spec officielle elle-même : une équipe peut légitimement définir ses propres types, que ce motif rejetterait à tort.
  • N'impose aucune limite de longueur sur la description : une bonne pratique courante (50-72 caractères pour la première ligne) reste une convention d'équipe, pas une règle de la spec Conventional Commits.
  • Le scope entre parenthèses doit être non vide dans ce motif (« docs(): » est rejeté) — un choix délibéré plus strict que plusieurs implémentations réelles comparées ici, qui l'acceptent sans le signaler comme cas limite.