Коммиты и pull request'ы¶
Единые правила для веток, коммитов и ревью. Применяются ко всем репозиториям команды.
Ветки¶
Имена¶
Формат — <type>/<kebab-short-description>:
feat/review-sse-throttle
fix/user-refresh-token-rollback
chore/bump-pgx
refactor/media-upload-session-state
docs/handbook-events-section
test/notification-retry-backoff
Префиксы:
| Префикс | Когда | Примеры |
|---|---|---|
feat/ |
Новая функциональность | feat/media-thumbnail-worker |
fix/ |
Исправление бага | fix/user-session-leak |
chore/ |
Не меняет поведение (bump зависимостей, CI, конфиг) | chore/bump-go-1-22 |
refactor/ |
Реорганизация кода без изменения поведения | refactor/extract-outbox-pkg |
docs/ |
Только документация | docs/handbook-logging |
test/ |
Только тесты / test infra | test/review-handler-tables |
Правила: - Только нижний регистр и дефисы. Никаких подчёркиваний и camelCase. - Короткое описание — 2–5 слов. Не пиши туда номер тикета. - Одна ветка = один PR = одна логическая правка.
Коммиты¶
Conventional Commits¶
Каждый commit-message — Conventional Commit:
Примеры:
feat(review): add SSE throttle for histogram updates
Throttle prevents bursty updates when a place gets many reviews at once.
Default limit is 5 events/sec per place.
---
fix(user): close refresh-token tx on rollback
The previous version leaked a pgx connection when refresh failed mid-tx.
---
chore(deps): bump pgx to v5.7.2
---
docs(handbook): document outbox publisher pattern
type— те же, что и для веток:feat,fix,chore,refactor,docs,test, плюсperf(оптимизация без изменения API) иci(изменения CI).scope— сервис или подсистема:user,review,media,notification,handbook,deps,ci.- Summary — императив в настоящем времени, нижний регистр, без точки в
конце:
add,fix,update, неadded,fixes,updated. - Длина summary — до 72 символов.
Тело коммита¶
Если изменение неочевидно — опиши почему, а не что. Diff расскажет, что.
Плохо:
Хорошо:
fix(user): invalidate guard cache on password change
Without invalidation, a freshly-changed password left the old cached
token-version in Redis for ~60s, so stale tokens continued to pass.
Размер коммита¶
- Один коммит = одна логическая правка. Не мешай рефакторинг и bug-fix в одном коммите.
- Автоматические правки (
gofmt,go mod tidy) — отдельным коммитом. - Ребейзь/squash локально до того, как откроешь PR, если вышла каша.
Pull Request¶
Размер¶
- Цель — ≤ 400 изменённых строк. Это не считая сгенерированных файлов (swagger, mock'и).
- Больше 400 — сначала подумай, можно ли разбить. Чаще всего можно: отдельный PR на интерфейс, отдельный на реализацию, отдельный на подключение в main.go.
- Если PR не бьётся — опиши в описании, почему единый PR неизбежен (например, миграция схемы + код в одной точке). Ревьюеры будут смотреть внимательнее.
Описание¶
Обязательный шаблон:
## Цель
Одним абзацем: зачем это изменение?
## Что сделано
- Ключевые правки списком. Не пересказывай diff построчно.
- Упоминай новые файлы, новые env-переменные, новые миграции.
## Как тестировать
- `make lint && make test`
- Конкретные команды / curl / шаги, по которым ревьюер проверит.
## Риски / совместимость
(Опционально) — если задеваются миграции, публичные API, формат событий.
Примеры того, что писать в «Риски»:
- «Добавлена новая миграция 005. Rolling-deploy безопасен: колонка nullable, старый код её игнорирует.»
- «Формат события
review.createdрасширен полемplace_name(optional). Schema-Version остаётся1, consumer'ы не ломаются.»
Ревью¶
Правила:
- Минимум один approve для merge.
- Два approve для security-sensitive областей:
- аутентификация / авторизация (в репозитории сервиса
user— файлinternal/service/auth.go, middleware auth), - крипто (подписание JWT, хеширование паролей, шифрование данных),
- новые миграции,
- изменения в outbox/events (риск потерь сообщений),
- любой код, который трогает секреты / токены / OAuth-конфигурацию.
- Автор не merge'ит без approve. Даже если reviewer промолчал сутки — пингуй, не merge'ь сам.
Как ревьюить:
- Смотри сначала описание PR. Если оно непонятное — проси автора уточнить до того, как начнёшь читать код.
- Проверяй по
checklists/pr-reviewer.md. - Комментарий «вопрос» vs «блокер» помечай явно. Префиксы
nit:,question:,blocker:экономят всем время. - Approve при остатках
nit— допустимо, если автор их точно увидит.
Как отвечать на комментарии:
- На каждый комментарий — либо правка, либо ответ, почему не правишь.
okбез правки — бесполезный ответ. Пиши, что сделал: «исправил в commit abcdef».- Разногласия разрешаются в комментариях, а не в чате (чтобы осталось в истории ревью).
Merge¶
- Squash merge — дефолт. История
mainлинейная, один PR = один commit. - Финальное сообщение squash-а — заголовок PR. Поэтому заголовок PR —
сразу в формате commit-message:
feat(review): add SSE throttle ... - После merge — удали ветку.
- Force-push в ветку PR — запрещён после того, как reviewer начал смотреть. До первого ревью — можно. Во время/после — только новые коммиты.
- Force-push в
main— запрещён всегда.
Правила по hooks и безопасности¶
- Никогда
git commit --no-verify. Если hook падает — чини проблему, а не подавляй проверку. - Никаких секретов в коммитах. Проверяй
git diffглазами перед push'ем. Если случайно закоммитил секрет: - Немедленно отзови секрет (сгенерируй новый, обнови в
.env.exampleкак placeholder). - Напиши в backend-канал.
- Не надейся, что
git rebase -iудалит секрет из истории — он уже в remote. .envв.gitignore. Только.env.exampleкоммитится, и он содержит placeholders, не реальные значения.- Не коммить сгенерированные бинари,
bin/,dist/,.idea/,.vscode/. Проверь.gitignoreперед первым PR в новый сервис.
Что не делать¶
- Не мержи PR с красным CI, даже если ты уверен, что это «flaky test». Flaky тест — отдельный issue, сначала чини/карантинируй его.
- Не пиши «drive-by» правки вне scope PR. Нашёл баг в соседнем файле — делай отдельный PR.
- Не добавляй в PR правку «заодно я ещё вот это переименовал» без упоминания в описании. Незаявленные правки — повод для re-request changes.