Модуль 7: Командная работа и продвинутые практики
Git — это не только инструмент для одного разработчика. Его главная сила проявляется в командной работе. В этом модуле мы разберём полный цикл: от создания Pull Request до релиза, включая code review, модели ветвления, stash, cherry-pick и теги.
Командная работа — это набор договорённостей. Git предоставляет механизмы, но культура и политики команды определяют, как именно их применять.
7.1 Pull Request / Merge Request
Pull Request (на GitHub) или Merge Request (на GitLab) — это запрос на слияние вашей ветки в основную. Это не просто «кнопка merge» — это полноценный процесс обсуждения и проверки кода.
Жизненный цикл PR
- Создание ветки —
git switch -c feature/user-profile - Разработка — коммиты, тесты, документация
- Push ветки —
git push -u origin feature/user-profile - Создание PR — через веб-интерфейс GitHub/GitLab
- Code Review — коллеги проверяют и комментируют
- Исправления — новые коммиты по замечаниям
- Approve — ревьюеры одобряют
- Merge — слияние в main
- Удаление ветки — ветка больше не нужна
Как написать хороший PR
Шаблон описания PR
## Что сделано Краткое описание изменений (1-3 предложения) ## Зачем Ссылка на задачу/тикет, мотивация изменений ## Как протестировать 1. Шаг 1 2. Шаг 2 3. Ожидаемый результат ## Скриншоты (если UI) ... ## Чеклист - [ ] Тесты написаны и проходят - [ ] Документация обновлена - [ ] Нет console.log / print для отладки
Создание PR через CLI
# GitHub CLI (gh)
gh pr create --title "feat: профиль пользователя" \
--body "Добавляет страницу профиля с аватаром и настройками" \
--base main
# Посмотреть свои PR
gh pr list --author @me
# Посмотреть статус проверок
gh pr checks
# Слить PR
gh pr merge --squash
Совет: Маленькие PR ревьюятся быстрее. Старайтесь, чтобы один PR содержал одно логическое изменение. PR на 50 строк получит ревью за час, PR на 500 строк — за неделю (если вообще).
7.2 Code Review: как давать и принимать ревью
Code review — это не «проверка на ошибки». Это процесс обмена знаниями, улучшения качества кода и выравнивания стандартов в команде.
Как проводить ревью (для ревьюера)
Чеклист ревьюера
- Корректность: код делает то, что заявлено? Есть ли edge-cases?
- Читаемость: понятен ли код без объяснений? Хорошие имена переменных?
- Архитектура: вписывается ли изменение в существующую структуру проекта?
- Тесты: покрыты ли основные сценарии? Тесты проходят?
- Безопасность: нет ли SQL-инъекций, утечек секретов, XSS?
- Производительность: нет ли N+1 запросов, утечек памяти?
Как писать комментарии
- Будьте конкретны: не «плохо», а «эта функция делает слишком много — предлагаю разбить на validateInput() и processData()»
- Объясняйте почему: не «переименуй», а «имя
dataне говорит о содержимом, предлагаюuserProfiles» - Разделяйте критичное и некритичное: используйте префиксы
nit:(мелочь),blocking:(нужно исправить) - Предлагайте решения: покажите код, а не только проблему
Как принимать ревью (для автора)
- Не воспринимайте замечания как критику лично — ревьюят код, не вас
- Отвечайте на каждый комментарий: «Исправил», «Не согласен, потому что...», «Давай обсудим»
- Правки делайте отдельными коммитами (чтобы ревьюер видел, что изменилось)
- После финального approve — squash/merge
# Посмотреть изменения в PR локально
gh pr checkout 42
# Или вручную:
git fetch origin pull/42/head:pr-42
git switch pr-42
7.4 Временное сохранение: git stash
Stash — это «карман» для незавершённых изменений. Типичная ситуация: вы работаете над фичей, и тут приходит срочный баг-репорт. Нужно переключиться на другую ветку, но текущие изменения ещё не готовы для коммита.
Основные команды
# Сохранить текущие изменения в stash
git stash push -m "WIP: форма логина"
# Или короткая форма
git stash
# Сохранить включая untracked файлы
git stash push -u -m "WIP: с новыми файлами"
# Посмотреть список stash'ей
git stash list
# stash@{0}: On feature/auth: WIP: форма логина
# stash@{1}: On main: WIP: рефакторинг
# Применить последний stash и удалить его
git stash pop
# Применить конкретный stash без удаления
git stash apply stash@{1}
# Посмотреть, что в stash'е (diff)
git stash show -p stash@{0}
# Удалить конкретный stash
git stash drop stash@{0}
# Удалить все stash'и
git stash clear
Практический сценарий
# Вы работаете над фичей...
# Приходит срочный баг:
# 1. Сохраняем незавершённую работу
git stash push -m "WIP: форма регистрации"
# 2. Переключаемся на main и создаём ветку для хотфикса
git switch main
git switch -c hotfix/critical-bug
# 3. Чиним баг, коммитим, мёржим
git commit -am "fix: критический баг в оплате"
git switch main
git merge hotfix/critical-bug
# 4. Возвращаемся к фиче и достаём stash
git switch feature/registration
git stash pop
# Продолжаем работу как ни в чём не бывало!
Совет: Всегда давайте stash'у осмысленное сообщение через -m. Через неделю stash@{3}: WIP ни о чём не скажет, а stash@{3}: WIP: форма логина с валидацией — понятно сразу.
7.5 Cherry-pick: перенос отдельных коммитов
cherry-pick берёт один конкретный коммит из другой ветки и применяет его к текущей. Это не merge целой ветки — это «вишенка с торта».
Когда использовать
- Хотфикс нужен и в main, и в release-ветке
- Из большой ветки нужен только один конкретный коммит
- Нужно вернуть коммит, который был потерян при неудачном rebase
# Перенести один коммит
git cherry-pick abc1234
# Перенести несколько коммитов подряд
git cherry-pick abc1234 def5678 ghi9012
# Перенести диапазон коммитов (от A до B включительно)
git cherry-pick A^..B
# Cherry-pick без автоматического коммита (только staged)
git cherry-pick --no-commit abc1234
# Если возник конфликт:
git cherry-pick --continue # после разрешения
git cherry-pick --abort # отменить
Осторожно: cherry-pick создаёт новый коммит с новым хешем (но тем же содержимым). Git не знает, что это «тот же» коммит. Если потом мержить ветки — возможны дублирования и конфликты.
7.6 Модели ветвления
Модель ветвления — это договорённость команды о том, какие ветки существуют, как они называются и когда сливаются.
GitHub Flow (простая модель)
Принцип: ветка → PR → merge
main— всегда рабочая, деплоится автоматически- Для каждой задачи создаётся ветка от main
- Готово → PR → code review → merge в main
- Нет отдельных веток develop, release, hotfix
Подходит для: небольших команд, SaaS-продуктов, непрерывного деплоя.
GitFlow (классическая модель)
Долгоживущие ветки
main— только релизы, каждый коммит = тег версииdevelop— текущая разработка, сюда мёржатся фичиfeature/*— ответвления от develop для каждой фичиrelease/*— подготовка релиза (фиксы, версии, документация)hotfix/*— срочные исправления от main
Подходит для: больших команд, продуктов с версионными релизами, мобильных приложений.
Trunk-based Development
Минимум ветвления
- Все работают в
main(trunk) - Ветки максимально короткоживущие (1-2 дня)
- Непрерывная интеграция — мёржим несколько раз в день
- Feature flags вместо долгих веток
Подходит для: команд с сильной CI/CD культурой, Google/Meta-масштаб.
7.7 Защищённые ветки и политики
Защита веток предотвращает случайные (и намеренные) нарушения процесса. Настраивается в GitHub/GitLab/Bitbucket.
Типичные политики
- Запрет push напрямую: все изменения только через PR
- Обязательный review: минимум 1-2 approve перед merge
- Обязательные CI-проверки: тесты, линтинг, сборка должны пройти
- Запрет force-push: нельзя переписывать историю защищённой ветки
- Подпись коммитов: обязательная GPG/SSH подпись
- Linear history: только rebase-merge или squash, без merge-коммитов
Минимальный набор для начала: защитите main от прямого push + обязательный 1 approve + CI-проверки. Этого достаточно для большинства команд.
7.8 Подпись коммитов (GPG/SSH)
Подпись коммитов подтверждает, что коммит действительно создан тем, за кого себя выдаёт автор. На GitHub подписанные коммиты получают значок «Verified».
# Настройка подписи через SSH (проще, чем GPG)
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
git config --global commit.gpgsign true
# Теперь все коммиты будут подписаны автоматически
git commit -m "feat: подписанный коммит"
# Проверить подпись
git log --show-signature
7.9 DCO и шаблоны PR
Developer Certificate of Origin — юридическое подтверждение авторства. Используется в open-source проектах (Linux kernel, CNCF-проекты).
# Добавить DCO sign-off к коммиту
git commit -s -m "feat: новая функция"
# Результат: сообщение + "Signed-off-by: Имя <email>"
# Добавить sign-off к последнему коммиту
git commit --amend -s --no-edit
7.10 Семантическое версионирование и релизы
Semantic Versioning (SemVer) — стандарт нумерации версий: MAJOR.MINOR.PATCH.
Правила SemVer
- MAJOR (1.x.x → 2.0.0): ломающие изменения API, несовместимость
- MINOR (1.1.x → 1.2.0): новая функциональность, обратная совместимость
- PATCH (1.1.1 → 1.1.2): баг-фиксы, без новой функциональности
# Полный цикл релиза:
# 1. Создать release-ветку
git switch -c release/1.2.0
# 2. Обновить версию в файлах (package.json, setup.py и т.д.)
# 3. Обновить CHANGELOG.md
# 4. Коммит и тег
git commit -am "release: v1.2.0"
git tag -a v1.2.0 -m "Release 1.2.0: добавлен профиль пользователя"
# 5. Слить в main и push
git switch main
git merge --no-ff release/1.2.0
git push origin main --tags
# 6. Создать GitHub Release (автоматически по тегу или вручную)
gh release create v1.2.0 --title "v1.2.0" --notes "Добавлен профиль пользователя"
Практическое задание
Задание 1: Полный цикл PR
- Создайте репозиторий на GitHub (или локально с
git init --bare) - Клонируйте, создайте ветку
feature/about-page - Сделайте 3 коммита, запушьте ветку
- Создайте PR (через
gh pr createили веб-интерфейс) - Добавьте описание по шаблону из раздела 7.1
Задание 2: Stash workflow
- Начните редактировать файл в feature-ветке (не коммитьте)
- Сохраните в stash:
git stash push -m "описание" - Переключитесь на main, сделайте хотфикс, вернитесь
- Восстановите stash:
git stash pop
Задание 3: Cherry-pick хотфикса
- В ветке
featureсделайте коммит с исправлением бага - Переключитесь на main
- Перенесите только этот коммит:
git cherry-pick <hash> - Проверьте, что исправление есть в обеих ветках