Модуль 9 · урок 3 з 9
Conventional Commits
Conventional Commits — домовленість про формат повідомлення коміту. Виглядає як зайва формальність, але дає три конкретні речі: читабельну історію, автоматичний changelog і можливість зрозуміти зміну, не відкриваючи діф.
Формат
<тип>(<скоуп>): <опис>
[тіло — навіщо, а не що]
[футер: BREAKING CHANGE, посилання на задачу]
feat(tasks): add status filter to task list
Filter state lives in the store and is reflected in query params,
so a filtered view can be shared by link.
Closes #12
Типи
| Тип | Коли | Приклад |
|---|---|---|
feat | Нова функціональність для користувача | feat(grid): add multi-column sorting |
fix | Виправлення бага | fix(forms): reset page on filter change |
refactor | Зміна коду без зміни поведінки | refactor(store): extract applyState |
perf | Оптимізація | perf(grid): add trackBy to task rows |
test | Тести | test(store): cover error recovery |
docs | Документація | docs: describe api contract |
style | Форматування, без зміни логіки | style: apply prettier |
chore | Службове: залежності, конфіги, CI | chore: bump angular to 22.1 |
fix — це виправлення того, що вже було в основній гілці й працювало
неправильно. Якщо ти правиш власний код у тій самій гілці, ще до PR, це не
fix — це частина тієї самої роботи, і краще її просто вмерджити в попередній
коміт. Інакше історія перетворюється на «feat: додав фільтр», «fix: полагодив фільтр»,
«fix: тепер точно».
Опис пишеться в наказовому способі
// ✅ що зробить цей коміт, якщо його застосувати
feat(grid): add multi-column sorting
fix(store): prevent duplicate requests on fast typing
// ❌ минулий час і опис процесу
feat(grid): added sorting
fix: fixed the bug
chore: some changes
Правило-підказка: коміт має продовжувати фразу «Якщо застосувати цей коміт, він…». «…add multi-column sorting» звучить логічно, «…added sorting» — ні.
Тіло: навіщо, а не що
fix(grid): reset page when filters change
Users reported an empty list after filtering. The page index stayed
at its previous value while the result set shrank, so the slice was
out of range. Resetting the page in one place — setFilters — keeps
this consistent for all filter types.
Closes #45
Що змінилось, видно з дифу. А от чому — ніде, крім повідомлення. Через рік саме
це тіло пояснить наступному розробнику, чому не можна просто прибрати page: 1,
який виглядає зайвим.
Ламальні зміни
feat(api)!: change task list response shape
BREAKING CHANGE: /api/tasks now returns { items, total } instead of a plain array.
Update all consumers to read response.items.
Знак оклику після скоупу плюс футер BREAKING CHANGE. Це те, що інструменти
автоматичної версійності перетворюють на підвищення мажорної версії, а люди — на привід
уважно прочитати PR.
Що це дає на практиці
# історія читається як список змін
git log --oneline
a1b2c3d feat(grid): add multi-column sorting
b2c3d4e fix(store): reset page on filter change
c3d4e5f refactor(store): extract applyState
d4e5f6a test(store): cover error recovery
# можна фільтрувати
git log --oneline --grep="^feat"
git log --oneline --grep="^fix" --since="1 month ago"
Автоматичний changelog приємний, але рідко потрібен у внутрішніх проєктах. Реальна користь інша: коли щось зламалось, ти шукаєш причину серед двадцяти комітів за тиждень. Якщо всі вони називаються «update» і «fixes», доводиться відкривати кожен. Якщо за форматом — потрібний знаходиться за пів хвилини.