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 компоненты
Пройдись по diff перед тем, как назначить ревьюера. Ты удивишься, сколько мусора найдёшь сам: забытые `fmt.Println`, закомментированный код, TODO без задачи.

Код-ревью: роль ревьюера

Ревью - это не поиск повода покритиковать. Это совместная работа над качеством кода. Развёрнутый чеклист ревьюера и типовые замечания - в уроке 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 и сборку образов.

Даже если «это только линтер ругается» - исправь. Привычка мержить с предупреждениями быстро приводит к тому, что pipeline всегда красный и никто на него не смотрит.

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

Зарегистрируйтесь бесплатно, чтобы пройти квиз, решить задание с автопроверкой и вести прогресс.