В main напрямую не коммитим. Любая задача идёт в отдельной ветке,
созданной от свежего main; в main работа попадает только после проверки.
main ← PR ← ветка {тип}/{говорящее-имя} ← коммиты ← прогнанные lint + typecheck + build
Имя ветки — {тип}/{говорящее-имя}: тип из таблицы ниже, имя описывает саму
работу, а не номер тикета (трекера у проекта нет). Примеры: feat/event-feed,
fix/layout-metadata, docs/git-workflow. Одна ветка — одна задача; ветка
живёт, пока задача не влита, и удаляется сразу после вливания.
Тип коммита (Conventional Commits):
| Тип | Когда |
|---|---|
feat |
новая функциональность |
fix |
исправление бага |
refactor |
переработка без смены поведения |
test |
тесты |
docs |
документация |
style |
форматирование, Tailwind-классы |
chore |
конфиг, зависимости, CI |
Scope — часть проекта, которую затронул коммит:
| Scope | Когда |
|---|---|
app |
роуты в app/ |
features |
сценарий в features/{name} (имя — в теме коммита) |
ui |
общие компоненты components/ui/ |
lib |
общая инфраструктура lib/ |
db |
миграции и сид supabase/ |
cfg |
next.config.ts, tsconfig, biome.json, зависимости, env |
docs |
документация |
ci |
CI/CD |
Появился новый крупный каталог — добавь для него строку в таблицу.
Примеры:
feat(app): добавлена главная страница со спискомfix(app): исправлены метаданные в корневом layoutrefactor(lib): вынесена генерация slug в отдельный модульchore(cfg): eslint заменён на biomedocs: обновлён git workflow под текущий проект
Номер задачи в сообщение не добавляем. Сообщение коммита — единственное место, где записано «почему», поэтому пиши причину, а не пересказ диффа.
git checkout main
git pull
git checkout -b {тип}/{говорящее-имя}Коммить по ходу, малыми атомарными шагами (см. ниже). Если main ушёл вперёд и
нужны его изменения — подтяни их в ветку: git merge main (или git rebase main,
пока ветка не запушена).
- Прогони проверки — они заменяют ревью, поэтому красная проверка — это незавершённая работа, а не «починю следом»:
npm run lint
npm run typecheck
npm run buildТе же три команды автоматически гоняет pre-push (см. «Git hooks»).
- Запушь ветку и открой PR в
main:
git push -u origin {тип}/{говорящее-имя}- После вливания PR удали ветку и обнови локальный
main:
git checkout main
git pull
git branch -d {тип}/{говорящее-имя}
git push origin --delete {тип}/{говорящее-имя}Хуки — husky, ставятся сами через
prepare при npm install. Файлы лежат в .husky/.
| Хук | Что делает |
|---|---|
pre-commit |
biome check --staged — линт и формат только застейдженных файлов |
pre-push |
npm run lint, npm run typecheck, npm run build |
Хук не обходим: --no-verify не используем. Упал хук — чини причину.
Один коммит — одно логическое изменение. Примеры правильного дробления:
refactor(lib): вынесена генерация slug в отдельный модуль
feat(lib): добавлен парсер даты активности
feat(app): добавлен компонент карточки активности
feat(app): добавлена страница списка
Не смешивай рефакторинг и фичу в одном коммите.