I Wrote the Rule Down; Nine of 3,580 Commits Follow It
In this repository's AGENTS.md, in two separate places, a commit rule is written down:
git commit -m "post: <kısa-başlık>"
I wrote that rule. The agents that write articles read that file on every run, and so do I. Today I wondered: how many commits actually follow it?
Nine. Nine out of three thousand five hundred and eighty.
This article started by chasing those nine and ended somewhere I did not expect: in the same repository, another rule I never wrote into any document holds at 96.9%. Understanding the gap between the two taught me more about writing documentation than about writing commits.
The limits of the measurement, stated up front
I pinned the measurement at 78c28382 — the commit immediately before this article, 4 November, 18:40. At that point the repository holds 3,622 commits; I dropped the merge commits, because git writes their messages, not me. The remaining 3,580 commits are the universe for every number here. The repository's first commit is 31 March 2026: 16.4 commits a day on average, over 218 days.
Two definitions will be needed. A commit counts as "content" if every path it touches starts with src/content/, src/assets/blog, src/assets/shorts, public/images or scripts/content-calendar.json; as "code" if none of them do; as "mixed" otherwise. And "body" means what git means by body — the text after the first blank line following the subject.
What I did not measure: whether a message is accurate (does the description really describe that change), my other repositories, and the language of the messages.
The written rule's reach: two and a half per thousand
Of the nine commits carrying the post: prefix, seven come from the bot that publishes the weekly series and two come from me. Two and a half per thousand.
There is something odd about the rule itself. The post type is not in the default list of the linter I will come to shortly; the rule I wrote into the document would not pass the first gate anyone might install in this repository. I added that line by hand on 20 April and then forgot it myself: the commit that publishes this article will start with feat: yeni makale — …, because it is written by a habit, not by my fingers.
CLAUDE.md — the other instruction file the agents read — mentions the git commit command but says nothing about the message format. So the repository's documented commit policy is this single, violated line.
The same file has been caught giving wrong numbers somewhere else, in a count from twenty-five days ago. The difference is this article's subject: there a number in the document had drifted away from the code; here a rule in the document was never applied at all.
The rule I never wrote down holds 96.9%
The overwhelming majority of messages in the repository follow Conventional Commits: a type, an optional parenthesised scope, an optional !, then a colon and a space, then the description. 3,470 of the 3,580 commits match that grammar to the letter. The 110 that do not carry no prefix at all.
| Type | Commits | Share |
|---|---|---|
| feat | 1,532 | 42.8% |
| chore | 1,443 | 40.3% |
| fix | 411 | 11.5% |
| (no prefix) | 110 | 3.1% |
| content | 20 | 0.6% |
| docs | 13 | 0.4% |
| perf | 10 | 0.3% |
| post | 9 | 0.3% |
| 14 other types | 32 | 0.9% |
So what holds that 96.9% up? Not a commit-msg hook, not commitlint, not a document. What holds it up is nine fixed strings inside the seven workflow files that call git commit: chore(social): mark posts as shared (multi-platform), feat: auto-generated content $(date +%Y-%m-%d), chore(faq): batch FAQ +${NEW_FAQ_COUNT} post (Schema.org FAQPage), chore: keep-alive touch [skip ci] and five siblings.
That is exactly where the difference lies. The post: rule sits in a document and requires someone to read and remember it. The other rule sits inside the command itself; it requires nobody to remember anything, because there is nothing to remember. I followed the rule I wrote in a document nine times; the rule I embedded in the execution path, two and a half thousand times.
You could call that a compliment: a machine's consistency beats a person's good day, every time. But it has a price, and the rest of this article is that price.
Price 1: the compliance does not serve a single tool
Conventional Commits exists to make the message readable by a tool, not by a person. The specification says so plainly: "Automatically generating CHANGELOGs", "Automatically determining a semantic version bump (based on the types of commits landed)", "Triggering build and publish processes". So that fix maps to PATCH, feat to MINOR and BREAKING CHANGE to MAJOR.
This repository hands those tools nothing. The version in package.json is 0.0.1. The only git tag is backup-pre-redesign-20260608 — a marker for a backup taken before a redesign on 8 June, not a version. No CHANGELOG. No semantic-release, no commitlint, no husky. The only installed hook is pre-commit, and it validates MDX files.
The specification has two instruments for MAJOR: the BREAKING CHANGE footer and a ! immediately before the colon. Across 3,580 commits the footer appears zero times; the ! appears exactly once, on an Astro security upgrade. Once in seven months.
Incidentally, the 1,532 feat commits are spread across 208 distinct days. If semantic-release were installed and ran one release per day — two assumptions, neither of them measured; I derived the number from the distribution — I would be on something like v1.208.0 today. I am on 0.0.1; SemVer 2.0.0 treats major version zero as being "for initial development", and the specification's FAQ recommends starting at 0.1.0. So my version number is not even a valid starting point; it is wherever npm init left it.
One last count: if I installed @commitlint/cli today with its default config-conventional, 154 commits (4.3%) in my history would not pass that gate. 110 have no prefix; the other 44 do match the grammar but use a type outside the eleven commitlint allows (build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test) — namely content, post, security, debug, ethics, shorts, copy, temp, backup, nginx and schema.
Here I have to correct myself. In my first draft I described those 44 commits as using a type "outside the specification". That is wrong: Conventional Commits has no closed list of types; the specification explicitly says types other than feat and fix MAY be used, and that additional types are not mandated. The closed list belongs to commitlint's default config. The convention itself is even looser than I assumed, which makes the absence of policing deeper, not shallower.
!Diagram
Price 2: compliant but unreadable
The second price of template-made compliance is repetition. Those 3,580 subjects contain only 1,183 distinct texts; the share of commits whose subject appears at least once more is 70.8%.
The record sits in a single line: chore(social): mark posts as shared (multi-platform) appears exactly 1,210 times, a third of the repository. Behind it come chore(content): topic-research verdict cache 105 times and — with no prefix at all — Publish 5 content updates 43 times.
That changes what I see when I open git log. Of the 40 commits in the last seven days, 18 are that one line; the change I am looking for is somewhere among the other 22. The remedy is not hard — filter with --author or --invert-grep — but the point stands: a history does not become readable by following a format. 3,470 messages that obey the convention are not a readable ledger while 1,210 of them are the same sentence.
Price 3: the field a human reads is empty
If that is the format's machine-facing side, its human-facing side is the body. Git's own documentation is clear: it is a good idea to begin with a "single short (no more than 50 characters) line summarizing the change", "followed by a blank line and then a more thorough description". The patch submission guide is blunter: the goal of your log message is "to convey the why behind your change".
2,694 of my 3,580 messages have a completely empty body. Another 80 have a body containing nothing but footer lines such as Co-Authored-By: — a signature, not a sentence to read. The number of commits with a readable body is 806: twenty-two and a half percent.
Subject lengths: median 52 characters, 90th percentile 79, longest 147. 2,137 subjects exceed 50 characters, 496 exceed 72, and 87 exceed 100.
I had to count those three numbers twice. The first pass, through awk '{print length($0)}', gave 2,141 / 532 / 146, and 159 for the longest. macOS's awk counts bytes, and in Turkish text ı, ş and ğ take two bytes each. Counted in characters it is 2,137 / 496 / 87, and 147. (gawk in a UTF-8 locale counts characters, so this trap depends on your tool.) Check a "50 characters" rule with a byte-counting tool and you will declare your own titles too long.
Looking at whose the long subjects are took the body discussion somewhere else. All 87 of the 87 subjects over 100 characters are mine; a bot never writes anything that long. 81 of the 87 carry a spaced dash in the middle with an explanation behind it, like fix(ci): deploy-only full-build timeout 60→100dk (1768 prerender ~67dk → bootstrap timeout oluyordu). That commit has no readable body — only a signature line — but the reason had already moved into the subject. 23 of the 87 long subjects are exactly this case.
I also looked by hand. I sorted my code commits without a readable body from newest to oldest and took every 16th; that left nine samples. Three of them still tell me the reason today — fix: wrap systemd ExecStart with /bin/bash so chmod loss cannot break deploy carries both the change and its justification in one line; a fourth is borderline, and you might not have counted it. Five only say what was done; two settle for Publish site updates, and for those two April commits I can only work out what was published by reading the diff. A sample of nine gives no ratio; what it gives is this: where there is no body, whether the subject carries the weight is a question to ask subject by subject.
Bots do not write bodies — except two of them
The same population sits behind all three prices. Twelve distinct names have committed to this repository; four are spellings of mine, 1,078 commits in total. The remaining 2,502 are machines.
I had already written that most commits on this blog come from bots, in a count of the night shift; that article's lesson was "do not let automation sign with your own name, or you will not be able to measure your own work later", and today I collected on it — the table below exists only because the signatures are separate.
| Who | What changed | Commits | No readable body |
|---|---|---|---|
| Machine | content only | 1,723 | 1,711 (99.3%) |
| Machine | content + code | 615 | 615 (100%) |
| Machine | code only | 164 | 154 (93.9%) |
| Me | code only | 606 | 135 (22.3%) |
| Me | content only | 360 | 129 (35.8%) |
| Me | content + code | 111 | 29 (26.1%) |
The column sums to 2,773, while the "completely empty body" figure in Price 3 is 2,694. The 79 in between are commits whose body holds only a signature line — counted here as having no readable body, not counted there as empty. One word, two definitions; fail to separate them and 80 commits move silently.
I was getting ready to look at that table and say "a bot does not write a body". It does: 2,480 of the machines' 2,502 commits have a completely empty body, but 22 do not. All 12 of Translation Bot's commits carry the line Auto-generated by translate-archive workflow., because the workflow passes git commit a second -m. The other 10 belong to the agent I have write code; those carry real bodies. So the body is not a machine-versus-human divide: it is about whether someone put that line in the template. The same thing again — what is in the template is what happens.
When a newline leaks into the template
I found the flip side of the template's power in the same repository. I did not want to assume how git finds the body: the documentation says "the text up to the first blank line" is "treated as the commit title", and that "that title is used throughout Git". I tried it with two commits in an empty repository (git 2.48.1):
git init -q .
printf 'subject line\n\nbody first line\n' | git commit -q --allow-empty -F -
printf 'subject line\nnext line, NO blank line\n' | git commit -q --allow-empty -F -
git log --format='S=[%s] B=[%b]'
The second commit's output: S=[subject line next line, NO blank line] B=[]. Skip the blank line and git joins the two lines into the title, leaving the body empty. The "why" you wrote is not lost — it is embedded in the title and shows up as a title in every list, every graph, every email.
It has happened twice in this repository. The subject of commits f3d79aa9 and e665aa65 is chore(i18n): TR to EN bulk translate +0 0 post. I found the cause in the archive translation workflow:
NEW_COUNT=$(git diff --staged --name-only --diff-filter=A | grep -c '\.en\.mdx$' || echo 0)
With no matches, grep -c prints "0" and exits 1; || echo 0 mistakes that for failure and adds another "0". NEW_COUNT becomes 0\n0, and the message template carries the newline through verbatim. Try it in your own shell and you will see the same. The fix is || true, or piping the result through tr -d '\n'; the irony is that the comment directly below that counter says "single-line commit message".
Where you write the rule matters more than what it says
Three questions came out of this audit, and all three look somewhere much wider than commit messages.
1. Does this rule require someone to remember it? If it does, the compliance rate can be two and a half per thousand and you will not notice for months. If you want a rule to actually hold, it has to get inside the command people already run — the template, the shell script, the hook, the wizard's default.
2. Who reads this rule? If nobody does, compliance is a form tax. You can keep paying it, but under "habit", not under "discipline". For seven months it never occurred to me to write BREAKING CHANGE, and nothing broke; filling in a field that cannot break is ritual.
3. What does a rule embedded in a template produce? Mine produced 96.9% compliance and the same sentence 1,210 times. A rule in the execution path is as thoughtless as it is cheap: you think about what it says once, and then it is repeated thousands of times.
I will not be installing commitlint. Fitting a gate that would reject 154 old commits and add a second to every commit I make, in order to protect a format nobody reads, would contradict this article's own finding. Instead I pulled the two post: lines in AGENTS.md towards what my workflows actually produce: both now read feat: yeni makale — <başlık> (TR+EN, kapaklar, takvim), and that change is inside this article's own commit. I fitted the document to the code, not the other way round. I was careful not to make a new promise: when I counted my promises two days ago, 11 of the 13 I could audit were still open — so I wrote the correction instead of the promise.
Because the real lesson is this: the document you write shapes your team's behaviour far less than your templates do. If you genuinely want a rule, do not explain it — put it in the way. Explain it and nothing more, and six months later you will count how many times it was followed and find nine.
Official Sources
- Git — git-commit documentation (DISCUSSION section)
- Git — SubmittingPatches: describe your changes well
- Git — pretty-formats: the %s and %b placeholders
- Semantic Versioning 2.0.0
- semantic-release/commit-analyzer — default release rules
- commitlint — config-conventional type list
- Conventional Commits specification repository
Mentions
I Wrote the Rule Down; Nine of 3,580 Commits Follow It In this repository's AGENTS.md, in two separate places, a commit rule is written down: git commit -m "post: <kısa-başlık>" I wrote that rule. The agents that write articles read that file on every run, and so do I. Today I wondered: how many commits actually follow it? Nine. Nine out of three thousand five hundred and eighty. This article started by chasing those nine and ended somewhere I did not expect: in the same repository, another rule I never wrote into any document holds at 96.9%. Understanding the gap between the two taught me more about writing documentation than about writing commits. The limits of the measurement, stated up front I pinned the measurement at 78c28382 — the commit immediately before this article, 4 November, 18:40. At that point the repository holds 3,622 commits; I dropped the merge commits, because git writes their messages, not me. The remaining 3,580 commits are the universe for every number here. The repository's first commit is 31 March 2026: 16.4 commits a day on average, over 218 days. Two definitions will be needed. A commit counts as "content" if every path it touches starts with src/content/, src/assets/blog, src/assets/shorts, public/images or scripts/content-calendar.json; as "code" if none of them do; as "mixed" otherwise. And "body" means what git means by body — the text after the first blank line following the subject. What I did not measure: whether a message is accurate (does the description really describe that change), my other repositories, and the language of the messages. The written rule's reach: two and a half per thousand Of the nine commits carrying the post: prefix, seven come from the bot that publishes the weekly series and two come from me. Two and a half per thousand. There is something odd about the rule itself. The post type is not in the default list of the linter I will come to shortly; the rule I wrote into the document would not pass the first gate anyone might install in this repository. I added that line by hand on 20 April and then forgot it myself: the commit that publishes this article will start with feat: yeni makale — …, because it is written by a habit, not by my fingers. CLAUDE.md — the other instruction file the agents read — mentions the git commit command but says nothing about the message format. So the repository's documented commit policy is this single, violated line. The same file has been caught giving wrong numbers somewhere else, in a count from twenty-five days ago. The difference is this article's subject: there a number in the document had drifted away from the code; here a rule in the document was never applied at all. The rule I never wrote down holds 96.9% The overwhelming majority of messages in the repository follow Conventional Commits: a type, an optional parenthesised scope, an optional !, then a colon and a space, then the description. 3,470 of the 3,580 commits match that grammar to the letter. The 110 that do not carry no prefix at all. | Type | Commits | Share | |---|---|---| | feat | 1,532 | 42.8% | | chore | 1,443 | 40.3% | | fix | 411 | 11.5% | | (no prefix) | 110 | 3.1% | | content | 20 | 0.6% | | docs | 13 | 0.4% | | perf | 10 | 0.3% | | post | 9 | 0.3% | | 14 other types | 32 | 0.9% | So what holds that 96.9% up? Not a commit-msg hook, not commitlint, not a document. What holds it up is nine fixed strings inside the seven workflow files that call git commit: chore(social): mark posts as shared (multi-platform), feat: auto-generated content $(date +%Y-%m-%d), chore(faq): batch FAQ +${NEW_FAQ_COUNT} post (Schema.org FAQPage), chore: keep-alive touch [skip ci] and five siblings. That is exactly where the difference lies. The post: rule sits in a document and requires someone to read and remember it. The other rule sits inside the command itself; it requires nobody to remember anything, because there is nothing to remember. I followed the rule I wrote in a document nine times; the rule I embedded in the execution path, two and a half thousand times. You could call that a compliment: a machine's consistency beats a person's good day, every time. But it has a price, and the rest of this article is that price. Price 1: the compliance does not serve a single tool Conventional Commits exists to make the message readable by a tool, not by a person. The specification says so plainly: "Automatically generating CHANGELOGs", "Automatically determining a semantic version bump (based on the types of commits landed)", "Triggering build and publish processes". So that fix maps to PATCH, feat to MINOR and BREAKING CHANGE to MAJOR. This repository hands those tools nothing. The version in package.json is 0.0.1. The only git tag is backup-pre-redesign-20260608 — a marker for a backup taken before a redesign on 8 June, not a version. No CHANGELOG. No semantic-release, no commitlint, no husky. The only installed hook is pre-commit, and it validates MDX files. The specification has two instruments for MAJOR: the BREAKING CHANGE footer and a ! immediately before the colon. Across 3,580 commits the footer appears zero times; the ! appears exactly once, on an Astro security upgrade. Once in seven months. Incidentally, the 1,532 feat commits are spread across 208 distinct days. If semantic-release were installed and ran one release per day — two assumptions, neither of them measured; I derived the number from the distribution — I would be on something like v1.208.0 today. I am on 0.0.1; SemVer 2.0.0 treats major version zero as being "for initial development", and the specification's FAQ recommends starting at 0.1.0. So my version number is not even a valid starting point; it is wherever npm init left it. One last count: if I installed @commitlint/cli today with its default config-conventional, 154 commits (4.3%) in my history would not pass that gate. 110 have no prefix; the other 44 do match the grammar but use a type outside the eleven commitlint allows (build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test) — namely content, post, security, debug, ethics, shorts, copy, temp, backup, nginx and schema. Here I have to correct myself. In my first draft I described those 44 commits as using a type "outside the specification". That is wrong: Conventional Commits has no closed list of types; the specification explicitly says types other than feat and fix MAY be used, and that additional types are not mandated. The closed list belongs to commitlint's default config. The convention itself is even looser than I assumed, which makes the absence of policing deeper, not shallower. !Diagram Price 2: compliant but unreadable The second price of template-made compliance is repetition. Those 3,580 subjects contain only 1,183 distinct texts; the share of commits whose subject appears at least once more is 70.8%. The record sits in a single line: chore(social): mark posts as shared (multi-platform) appears exactly 1,210 times, a third of the repository. Behind it come chore(content): topic-research verdict cache 105 times and — with no prefix at all — Publish 5 content updates 43 times. That changes what I see when I open git log. Of the 40 commits in the last seven days, 18 are that one line; the change I am looking for is somewhere among the other 22. The remedy is not hard — filter with --author or --invert-grep — but the point stands: a history does not become readable by following a format. 3,470 messages that obey the convention are not a readable ledger while 1,210 of them are the same sentence. Price 3: the field a human reads is empty If that is the format's machine-facing side, its human-facing side is the body. Git's own documentation is clear: it is a good idea to begin with a "single short (no more than 50 characters) line summarizing the change", "followed by a blank line and then a more thorough description". The patch submission guide is blunter: the goal of your log message is "to convey the why behind your change". 2,694 of my 3,580 messages have a completely empty body. Another 80 have a body containing nothing but footer lines such as Co-Authored-By: — a signature, not a sentence to read. The number of commits with a readable body is 806: twenty-two and a half percent. Subject lengths: median 52 characters, 90th percentile 79, longest 147. 2,137 subjects exceed 50 characters, 496 exceed 72, and 87 exceed 100. I had to count those three numbers twice. The first pass, through awk '{print length($0)}', gave 2,141 / 532 / 146, and 159 for the longest. macOS's awk counts bytes, and in Turkish text ı, ş and ğ take two bytes each. Counted in characters it is 2,137 / 496 / 87, and 147. (gawk in a UTF-8 locale counts characters, so this trap depends on your tool.) Check a "50 characters" rule with a byte-counting tool and you will declare your own titles too long. Looking at whose the long subjects are took the body discussion somewhere else. All 87 of the 87 subjects over 100 characters are mine; a bot never writes anything that long. 81 of the 87 carry a spaced dash in the middle with an explanation behind it, like fix(ci): deploy-only full-build timeout 60→100dk (1768 prerender ~67dk → bootstrap timeout oluyordu). That commit has no readable body — only a signature line — but the reason had already moved into the subject. 23 of the 87 long subjects are exactly this case. I also looked by hand. I sorted my code commits without a readable body from newest to oldest and took every 16th; that left nine samples. Three of them still tell me the reason today — fix: wrap systemd ExecStart with /bin/bash so chmod loss cannot break deploy carries both the change and its justification in one line; a fourth is borderline, and you might not have counted it. Five only say what was done; two settle for Publish site updates, and for those two April commits I can only work out what was published by reading the diff. A sample of nine gives no ratio; what it gives is this: where there is no body, whether the subject carries the weight is a question to ask subject by subject. Bots do not write bodies — except two of them The same population sits behind all three prices. Twelve distinct names have committed to this repository; four are spellings of mine, 1,078 commits in total. The remaining 2,502 are machines. I had already written that most commits on this blog come from bots, in a count of the night shift; that article's lesson was "do not let automation sign with your own name, or you will not be able to measure your own work later", and today I collected on it — the table below exists only because the signatures are separate. | Who | What changed | Commits | No readable body | |---|---|---|---| | Machine | content only | 1,723 | 1,711 (99.3%) | | Machine | content + code | 615 | 615 (100%) | | Machine | code only | 164 | 154 (93.9%) | | Me | code only | 606 | 135 (22.3%) | | Me | content only | 360 | 129 (35.8%) | | Me | content + code | 111 | 29 (26.1%) | The column sums to 2,773, while the "completely empty body" figure in Price 3 is 2,694. The 79 in between are commits whose body holds only a signature line — counted here as having no readable body, not counted there as empty. One word, two definitions; fail to separate them and 80 commits move silently. I was getting ready to look at that table and say "a bot does not write a body". It does: 2,480 of the machines' 2,502 commits have a completely empty body, but 22 do not. All 12 of Translation Bot's commits carry the line Auto-generated by translate-archive workflow., because the workflow passes git commit a second -m. The other 10 belong to the agent I have write code; those carry real bodies. So the body is not a machine-versus-human divide: it is about whether someone put that line in the template. The same thing again — what is in the template is what happens. When a newline leaks into the template I found the flip side of the template's power in the same repository. I did not want to assume how git finds the body: the documentation says "the text up to the first blank line" is "treated as the commit title", and that "that title is used throughout Git". I tried it with two commits in an empty repository (git 2.48.1): git init -q . printf 'subject line\n\nbody first line\n' | git commit -q --allow-empty -F - printf 'subject line\nnext line, NO blank line\n' | git commit -q --allow-empty -F - git log --format='S=[%s] B=[%b]' The second commit's output: S=[subject line next line, NO blank line] B=[]. Skip the blank line and git joins the two lines into the title, leaving the body empty. The "why" you wrote is not lost — it is embedded in the title and shows up as a title in every list, every graph, every email. It has happened twice in this repository. The subject of commits f3d79aa9 and e665aa65 is chore(i18n): TR to EN bulk translate +0 0 post. I found the cause in the archive translation workflow: NEW_COUNT=$(git diff --staged --name-only --diff-filter=A | grep -c '\.en\.mdx$' || echo 0) With no matches, grep -c prints "0" and exits 1; || echo 0 mistakes that for failure and adds another "0". NEW_COUNT becomes 0\n0, and the message template carries the newline through verbatim. Try it in your own shell and you will see the same. The fix is || true, or piping the result through tr -d '\n'; the irony is that the comment directly below that counter says "single-line commit message". Where you write the rule matters more than what it says Three questions came out of this audit, and all three look somewhere much wider than commit messages. 1. Does this rule require someone to remember it? If it does, the compliance rate can be two and a half per thousand and you will not notice for months. If you want a rule to actually hold, it has to get inside the command people already run — the template, the shell script, the hook, the wizard's default. 2. Who reads this rule? If nobody does, compliance is a form tax. You can keep paying it, but under "habit", not under "discipline". For seven months it never occurred to me to write BREAKING CHANGE, and nothing broke; filling in a field that cannot break is ritual. 3. What does a rule embedded in a template produce? Mine produced 96.9% compliance and the same sentence 1,210 times. A rule in the execution path is as thoughtless as it is cheap: you think about what it says once, and then it is repeated thousands of times. I will not be installing commitlint. Fitting a gate that would reject 154 old commits and add a second to every commit I make, in order to protect a format nobody reads, would contradict this article's own finding. Instead I pulled the two post: lines in AGENTS.md towards what my workflows actually produce: both now read feat: yeni makale — <başlık> (TR+EN, kapaklar, takvim), and that change is inside this article's own commit. I fitted the document to the code, not the other way round. I was careful not to make a new promise: when I counted my promises two days ago, 11 of the 13 I could audit were still open — so I wrote the correction instead of the promise. Because the real lesson is this: the document you write shapes your team's behaviour far less than your templates do. If you genuinely want a rule, do not explain it — put it in the way. Explain it and nothing more, and six months later you will count how many times it was followed and find nine. Official Sources - Git — git-commit documentation (DISCUSSION section) - Git — SubmittingPatches: describe your changes well - Git — pretty-formats: the %s and %b placeholders - Semantic Versioning 2.0.0 - semantic-release/commit-analyzer — default release rules - commitlint — config-conventional type list - Conventional Commits specification repository