changelog-discipline
CHANGELOG фиксирует каждое законченное изменение кода, но не пересказывает
каждый файл и коммит. Механическая правка получает короткую запись; решение —
контекст, которого нет в коде: почему сделали именно так, что было до этого и
что отвергли.
Scope
- Применять после каждого законченного изменения кода в проекте, где ведётся
changelog.
- Применять при настройке changelog в новом проекте.
- Применять при подготовке релиза.
- Не применять для сообщений коммитов, описаний PR и релиз-нот для
пользователей — другие форматы, другие читатели.
Core Principles
- Пишется для того, кто вернётся через полгода. Обычно это сам автор,
забывший контекст.
- Полнота не требует оценки важности. Менялся код — появилась запись. Один
пункт описывает цельное изменение, а не каждый файл или коммит.
- Глубина зависит от решения. Для механической правки достаточно назвать
область и явно сказать, что поведение не изменилось. Для неочевидного решения
нужны причина, прежнее состояние и отвергнутые варианты.
- «Почему» дороже «что». Что изменилось — видно в диффе. Почему выбрали
этот вариант — не видно нигде.
- Changelog не описывает текущее состояние. Актуальное правило живёт в
коде, конфигурации или контракте; changelog объясняет, почему оно изменилось,
и указывает, где его искать.
- Отвергнутая альтернатива ценнее описания принятой. Она не даст через
полгода переделать обратно и наступить на те же грабли.
- Запись делается сразу, а не перед релизом. Иначе полноту уже нельзя
проверить по ходу работы, а причины решений успевают забыться.
Формат
Структура файла
# Changelog
Все заметные изменения <проект>. Формат — Keep a Changelog.
---
## [Unreleased]
### Added
### Changed
### Fixed
---
## [0.1.3] — 2026-07-31
### <Заголовок релиза — одной фразой о сути>
- **Что:** …
- **Где:** …
- **Почему:** …
- **Было:** …
### Added
### Changed
### Fixed
Резюме релиза — четыре поля
Самая ценная часть. Не пересказ пунктов ниже, а ответ на вопрос «что вообще
поменялось в продукте»:
| Поле |
Что отвечает |
| Что |
что теперь работает иначе, в терминах продукта, а не кода |
| Где |
какие файлы и области затронуты — точка входа для того, кто полезет разбираться |
| Почему |
какую боль это снимает; ради чего вообще делалось |
| Было |
как вело себя до — иначе через полгода непонятно, что чинили |
Поле Было чаще всего пропускают, и зря: без него запись описывает мир,
которого читатель не помнит.
Пункты внутри секций
Одна запись = одно законченное изменение, а не один файл или коммит. Внутри:
- жирный заголовок — суть одной фразой
- что поменялось и где
- для механической правки — явное «поведение не изменилось»
- для неочевидного решения — почему выбрали так, как было раньше и что отвергли
Пример:
ПКМ вместо всплывающего меню по ховеру. Копирование ссылки из текста
переехало в контекстное меню (LinkContextMenu). Сначала это было всплывающее
по ховеру микро-меню, но до кнопки не успевал доехать курсор — контекстное
меню совпадает с поведением родного текстового поля и не требует ни за чем
успевать.
Здесь есть отвергнутый вариант и причина отказа. Через полгода это не даст
«улучшить» обратно.
Workflow
- После каждого законченного изменения кода — сразу дописать один пункт в
[Unreleased], в подходящую секцию (Added / Changed / Fixed).
- Выбрать глубину. Механическую правку записать одной строкой с пометкой,
что поведение не изменилось. Для изменения поведения или неочевидного решения
добавить причину, прежнее состояние и отвергнутые варианты.
- Формулировать от продукта, когда поведение изменилось: не «добавил
параметр», а «теперь можно X».
- При релизе — превратить
[Unreleased] в версию с датой и написать резюме
из четырёх полей.
Проверка качества
Проверка полноты проста: если менялся код, в [Unreleased] появился пункт про
цельное изменение.
Для механической правки достаточно ответить:
- где менялось;
- подтверждено ли, что поведение осталось прежним.
Для изменения поведения или решения запись должна отвечать:
- что изменилось для пользователя;
- почему сделали так, а не иначе;
- где смотреть код;
- как было раньше.
Если по changelog приходится восстанавливать актуальные значения или правила —
они лежат не там; запись должна ссылаться на действующий источник.
References
references/01-antipatterns.md — как не надо, с разбором
references/02-examples.md — примеры записей до и после
1---2name: changelog-discipline3description: Write and maintain a CHANGELOG that records every completed code change without becoming a commit dump. Use after any code change in a project that has a changelog, when setting one up, when preparing a release, or when the user asks why something was built this way. Keep mechanical entries brief; preserve reasons and rejected alternatives for non-obvious decisions. Do not use for commit messages, PR descriptions, or user-facing release notes.4---56# changelog-discipline78CHANGELOG фиксирует **каждое законченное изменение кода**, но не пересказывает9каждый файл и коммит. Механическая правка получает короткую запись; решение —10контекст, которого нет в коде: почему сделали именно так, что было до этого и11что отвергли.1213## Scope1415- Применять после **каждого законченного изменения кода** в проекте, где ведётся16 changelog.17- Применять при настройке changelog в новом проекте.18- Применять при подготовке релиза.19- Не применять для сообщений коммитов, описаний PR и релиз-нот для20 пользователей — другие форматы, другие читатели.2122## Core Principles2324- **Пишется для того, кто вернётся через полгода.** Обычно это сам автор,25 забывший контекст.26- **Полнота не требует оценки важности.** Менялся код — появилась запись. Один27 пункт описывает цельное изменение, а не каждый файл или коммит.28- **Глубина зависит от решения.** Для механической правки достаточно назвать29 область и явно сказать, что поведение не изменилось. Для неочевидного решения30 нужны причина, прежнее состояние и отвергнутые варианты.31- **«Почему» дороже «что».** Что изменилось — видно в диффе. Почему выбрали32 этот вариант — не видно нигде.33- **Changelog не описывает текущее состояние.** Актуальное правило живёт в34 коде, конфигурации или контракте; changelog объясняет, почему оно изменилось,35 и указывает, где его искать.36- **Отвергнутая альтернатива ценнее описания принятой.** Она не даст через37 полгода переделать обратно и наступить на те же грабли.38- **Запись делается сразу, а не перед релизом.** Иначе полноту уже нельзя39 проверить по ходу работы, а причины решений успевают забыться.4041## Формат4243### Структура файла4445```markdown46# Changelog4748Все заметные изменения <проект>. Формат — Keep a Changelog.4950---5152## [Unreleased]5354### Added55### Changed56### Fixed5758---5960## [0.1.3] — 2026-07-316162### <Заголовок релиза — одной фразой о сути>6364- **Что:** …65- **Где:** …66- **Почему:** …67- **Было:** …6869### Added70### Changed71### Fixed72```7374### Резюме релиза — четыре поля7576Самая ценная часть. Не пересказ пунктов ниже, а ответ на вопрос «что вообще77поменялось в продукте»:7879| Поле | Что отвечает |80|---|---|81| **Что** | что теперь работает иначе, в терминах продукта, а не кода |82| **Где** | какие файлы и области затронуты — точка входа для того, кто полезет разбираться |83| **Почему** | какую боль это снимает; ради чего вообще делалось |84| **Было** | как вело себя до — иначе через полгода непонятно, что чинили |8586Поле **Было** чаще всего пропускают, и зря: без него запись описывает мир,87которого читатель не помнит.8889### Пункты внутри секций9091Одна запись = одно законченное изменение, а не один файл или коммит. Внутри:9293- **жирный заголовок** — суть одной фразой94- что поменялось и где95- для механической правки — явное «поведение не изменилось»96- для неочевидного решения — почему выбрали так, как было раньше и что отвергли9798Пример:99100> **ПКМ вместо всплывающего меню по ховеру.** Копирование ссылки из текста101> переехало в контекстное меню (`LinkContextMenu`). Сначала это было всплывающее102> по ховеру микро-меню, но до кнопки не успевал доехать курсор — контекстное103> меню совпадает с поведением родного текстового поля и не требует ни за чем104> успевать.105106Здесь есть отвергнутый вариант и причина отказа. Через полгода это не даст107«улучшить» обратно.108109## Workflow1101111. **После каждого законченного изменения кода** — сразу дописать один пункт в112 `[Unreleased]`, в подходящую секцию (Added / Changed / Fixed).1132. **Выбрать глубину.** Механическую правку записать одной строкой с пометкой,114 что поведение не изменилось. Для изменения поведения или неочевидного решения115 добавить причину, прежнее состояние и отвергнутые варианты.1163. **Формулировать от продукта**, когда поведение изменилось: не «добавил117 параметр», а «теперь можно X».1184. **При релизе** — превратить `[Unreleased]` в версию с датой и написать резюме119 из четырёх полей.120121## Проверка качества122123Проверка полноты проста: если менялся код, в `[Unreleased]` появился пункт про124цельное изменение.125126Для механической правки достаточно ответить:127128- где менялось;129- подтверждено ли, что поведение осталось прежним.130131Для изменения поведения или решения запись должна отвечать:132133- что изменилось для пользователя;134- почему сделали так, а не иначе;135- где смотреть код;136- как было раньше.137138Если по changelog приходится восстанавливать актуальные значения или правила —139они лежат не там; запись должна ссылаться на действующий источник.140141## References142143- `references/01-antipatterns.md` — как не надо, с разбором144- `references/02-examples.md` — примеры записей до и после