Pull Request / Merge Request: как работать в команде
В одиночку можно коммитить прямо в main и надеяться на лучшее. В команде так не работает. Merge Request (MR) - это механизм, через который код попадает в основную ветку только после проверки другим человеком. Это не бюрократия, а страховка: второй взгляд ловит баги, архитектурные просчёты и опечатки, которые автор просто не замечает после нескольких часов работы.
MR - это ещё и документация. Через полгода, когда кто-то спросит «зачем мы поменяли формат ответа в API», ответ будет в описании MR, а не в чьей-то голове.
PR vs MR: терминология
GitHub называет это Pull Request (PR), GitLab - Merge Request (MR). Суть одинаковая: «я хочу влить свою ветку в целевую, посмотрите код». В Bitbucket тоже используют Pull Request. В разговоре разработчики часто говорят «пулл-реквест» независимо от платформы - это нормально, все понимают.
GitHub → Pull Request (PR)
GitLab → Merge Request (MR)
Bitbucket → Pull Request (PR)
Azure DevOps → Pull Request (PR)
В этом уроке мы используем термин MR, потому что проект работает на GitLab. Но всё сказанное применимо к PR на GitHub.
Анатомия хорошего MR
Хороший MR - это не просто «я запушил ветку, разберитесь». У него есть структура, которая помогает ревьюеру понять контекст за минуту.
Заголовок
Заголовок должен быть коротким и информативным. Хорошая практика - включать номер задачи:
FL-142 feat: add rate limiting to auth endpoints
FL-89 fix: correct token expiration check
FL-201 refactor: extract email validation to domain layer
Плохие заголовки:
fix stuff # что именно?
WIP # это не заголовок
changes # спасибо, очень информативно
Описание
Описание - самая важная часть MR. Вот шаблон, который работает:
## Что сделано
- Добавлен rate limiting на /auth/sessions (10 req/min)
- Добавлен rate limiting на /users (5 req/min для регистрации)
- Используется httprate middleware
## Зачем
Защита от брутфорс-атак на авторизацию (FL-142).
## Как проверить
1. Запустить `docker-compose up -d`
2. Отправить 11 запросов на POST /auth/sessions за минуту
3. Убедиться, что 11-й возвращает 429
## Связанные задачи
- Closes FL-142
Labels и Assignees
В GitLab MR можно пометить лейблами - backend, frontend, bugfix, breaking-change. Это помогает фильтровать MR в больших проектах. Назначай ревьюеров явно: если MR висит без assignee, его никто не посмотрит.
Labels: backend, security
Assignee: @lead-developer
Reviewer: @teammate
Milestone: v1.2.0
Шаблоны MR в GitLab
Чтобы не писать структуру описания каждый раз, создай шаблон. GitLab ищет шаблоны в папке .gitlab/merge_request_templates/:
mkdir -p .gitlab/merge_request_templates
Создай файл .gitlab/merge_request_templates/Default.md:
## Что сделано
-
## Зачем
<!-- Ссылка на задачу или описание проблемы -->
## Как проверить
1.
## Чеклист
- [ ] Тесты написаны и проходят
- [ ] Документация обновлена
- [ ] Нет TODO без задачи в трекере
- [ ] Миграции обратимы
Теперь при создании нового MR шаблон подставляется автоматически. Можно создать несколько шаблонов - Feature.md, Bugfix.md, Hotfix.md - и выбирать нужный.
Draft MR: работа в процессе
Если ты хочешь показать код до того, как он готов к ревью, открой Draft MR. В GitLab это делается добавлением Draft: в начало заголовка:
Draft: FL-142 feat: add rate limiting to auth endpoints
Draft MR нельзя замержить случайно - кнопка Merge заблокирована. Это удобно для:
- раннего обсуждения архитектурного подхода
- получения фидбека по направлению работы
- запуска CI/CD на промежуточном коде
- информирования команды, что задача в работе
Когда код готов, убери Draft: из заголовка или нажми кнопку «Mark as ready» в интерфейсе.
Код-ревью: роль автора
Автор MR может сильно упростить жизнь ревьюеру:
Перед открытием MR:
# Убедись, что ветка актуальна
git fetch origin
git rebase origin/develop
# Проверь, что тесты проходят
make test
# Посмотри diff глазами ревьюера
git diff origin/develop...HEAD
Размер MR имеет значение. MR на 50 строк получает детальное ревью. MR на 500 строк получает «LGTM» через 3 дня, потому что никто не хочет в это погружаться.
Рекомендованный размер: до 200-300 изменённых строк
Максимум: 400-500 строк (только если это неразделимое изменение)
Если задача большая, разбей её на несколько MR:
MR 1: Добавить domain модели и миграции
MR 2: Добавить repository и service layer
MR 3: Добавить HTTP handlers и роуты
MR 4: Добавить frontend компоненты
Код-ревью: роль ревьюера
Ревью - это не поиск повода покритиковать. Это совместная работа над качеством кода. Развёрнутый чеклист ревьюера и типовые замечания - в уроке code review из трека clean code.
На что смотреть:
- Корректность логики - делает ли код то, что заявлено?
- Обработка ошибок - что будет, если БД недоступна? Если входные данные невалидны?
- Тесты - покрывают ли они основные сценарии?
- Именование - понятны ли названия переменных и функций через месяц?
- Безопасность - нет ли SQL-инъекций, утечек данных, хардкода секретов?
Как писать комментарии:
# Плохо:
"Это неправильно"
"Зачем ты так сделал?"
# Хорошо:
"Здесь может быть nil pointer, если user не найден.
Предлагаю добавить проверку: if user == nil { return ErrNotFound }"
"Nit: переименовать `d` в `duration` для читаемости"
Используй префиксы для комментариев:
nit: - мелочь, не блокирует мерж
question: - хочу понять, почему так
suggestion: - предлагаю альтернативу
blocker: - это нужно исправить перед мержем
Squash on Merge
При мерже MR можно объединить все коммиты ветки в один. Это называется squash - тот же результат можно получить и локально через interactive rebase. В GitLab опция доступна прямо на странице MR.
Когда это полезно:
# Ветка с такой историей:
a1b2c3 WIP: начал делать
d4e5f6 fix typo
g7h8i9 oops, forgot file
j1k2l3 actually fix the thing
m4n5o6 FL-142 feat: add rate limiting
# После squash в main попадёт один чистый коммит:
x9y8z7 FL-142 feat: add rate limiting to auth endpoints
В настройках проекта GitLab можно включить squash по умолчанию: Settings → Merge Requests → Squash commits → Encourage/Require.
CI/CD и MR
В правильно настроенном проекте pipeline запускается автоматически при каждом пуше в ветку MR. MR нельзя замержить, пока pipeline красный.
# .gitlab-ci.yml - pipeline запускается на MR
stages:
- lint
- test
lint:
stage: lint
script:
- golangci-lint run ./...
rules:
- if: $CI_MERGE_REQUEST_ID
test:
stage: test
script:
- go test ./... -count=1 -race
rules:
- if: $CI_MERGE_REQUEST_ID
GitLab показывает статус pipeline прямо на странице MR - зелёная галочка или красный крестик. Это убирает вопросы вроде «а тесты проходят?». Как собрать такой pipeline целиком - в уроке про GitLab CI и сборку образов.
Auto-merge
Если MR прошёл ревью, но pipeline ещё работает, можно включить auto-merge. GitLab замержит MR автоматически, как только pipeline станет зелёным.
Это удобно в конце рабочего дня: ревьюер одобрил, ты включил auto-merge и пошёл домой. Не нужно ждать 10 минут, пока pipeline отработает.
Обсуждения и треды
Комментарии в MR организованы в треды (threads). Каждый тред - это отдельное обсуждение, которое можно разрешить (resolve). MR можно настроить так, чтобы мерж был невозможен, пока есть неразрешённые треды.
Тред 1: [Resolved] Переименовать переменную
Тред 2: [Unresolved] Добавить обработку ошибки ← блокирует мерж
Тред 3: [Resolved] Обновить документацию
Разрешает тред тот, кто его создал - это подтверждение, что замечание учтено.
Мини-задание
- Создай ветку
feature/test-mrи открой MR в свой проект - Добавь в MR описание по шаблону: что сделано, зачем, как проверить
- Создай файл
.gitlab/merge_request_templates/Default.mdс шаблоном - Пройдись по diff своего MR и оставь себе комментарий с замечанием
- Попробуй включить опцию squash on merge