Процесс разработки: ветка demo, rebase и два pull request

Схема с промежуточной веткой demo: фичи льются в неё, тестируются, и только потом уходят в main. Плюс правила оформления коммитов и разница между rebase и merge.

v2 0 stars 0 forks 0 watchers 1 branch 0 runs Public
Добавлен раздел про область изменения в скобках (scope). Исправлены сбитые символы.v2
Зачем промежуточная ветка

В простой схеме фичи льются сразу в main. Пока разработчик один, это работает. Как только появляется необходимость проверить несколько фич вместе до выкатки, нужна промежуточная ветка.

Здесь она называется demo. В других проектах встретишь develop, development или staging — суть одна.

code
1feature/твоя-фича → demo → main
2 первый PR второй PR
3 (ревью) (релиз)

Главное отличие от простой схемы: два pull request вместо одного, и ветка ответвляется от demo, а не от main.

Как оформлять коммиты

Полная форма сообщения выглядит так:

code
1тип(область): описание в повелительном наклонении

Пять правил:

  1. Типfeat, fix, docs, style, refactor, test, chore.
  2. Повелительное наклонение — «добавь», а не «добавил».
  3. Описывай ЧТО сделано, а не КАК.
  4. Первая строка до 50 символов.
  5. Подробности — после пустой строки.

Примеры по-русски:

yaml
1feat: добавлен модуль авторизации
2fix: исправлен баг с регистрацией пользователя
3docs: обновлена документация API
4refactor: переработка модуля платежей
5test: добавлены тесты для API эндпоинтов
6chore: обновлены зависимости проекта

Примеры по-английски:

yaml
1feat: add user authentication via JWT
2fix: resolve database connection timeout
3refactor: optimize course search algorithm
4test: add integration tests for payment module
5chore: upgrade FastAPI to v0.100.0

Язык выбирает команда — важно только, чтобы в одном проекте он был один.

Что писать в скобочках

Скобки после типа — это область изменения (scope). Одно слово: какой части проекта касается коммит.

code
1fix(git): успешный push не становится ошибкой
2chore(deps): закрыты уязвимости ip-address и fast-uri
3fix(ui): длинные названия больше не распирают мобильную вёрстку
4feat(mcp): точечная правка списка
5fix(cache): закрытие списка отзывает его у общего кеша сразу
6feat(safety): разрушительная команда не попадает в исполняемые

Прочитав такую строку, ты понимаешь куда смотреть, ещё не открыв диф. Без области — «fix: исправлен баг» — приходится лезть в коммит, чтобы понять, о чём он вообще.

Правила для области:

ПравилоКакКак не надо
Одно слово, строчнымиfix(auth)fix(Модуль Авторизации)
Часть системы, а не файлfix(cache)fix(redis_client.py)
Из устоявшегося набораapi, ui, db, auth, depsкаждый раз новое слово
Не дублирует типfeat(cart)feat(feature)

Набор областей у проекта конечный: обычно 5–15 штук. Их стоит один раз выписать в CONTRIBUTING.md и дальше выбирать из списка, а не сочинять на ходу. Иначе через полгода в истории будет auth, authorization, authz и users-auth — и польза от области пропадёт.

Область необязательна. Если изменение общее и не привязано к части системы — пиши без скобок: chore: обновлены зависимости. Пустые скобки fix(): ... — ошибка, так не пишут.

Ломающее изменение помечается восклицательным знаком после скобок:

code
1feat(api)!: убран устаревший эндпоинт /v1/users

Это сигнал: у того, кто пользуется твоим кодом, после обновления что-то сломается.

Что должно стоять в скобках в сообщении коммита?

Цикл

1
Обновить demo и ответвиться от неё
bash
1git switch demo
2git pull origin demo
3git switch -c feature/your-name-of-feature

Ключевое: ветка создаётся от demo, а не от main. Ответвишься от main — получишь конфликты со всем, что уже влили в demo до тебя.

Why: Ветка должна ответвляться оттуда, куда потом вольётся. Это главное правило любой схемы ветвления, и его чаще всего нарушают.
$git switch demo && git pull origin demo
Check
  • Ветка создана от demo, а не от main
  • Имя ветки с префиксом и описывает задачу
2
Закоммитить изменения
bash
1git add .
2git commit -m "feat(cart): добавлено удаление товара из корзины"

Перед git add . всегда смотри git status — точка забирает всё, включая то, что ты не собирался коммитить.

Why: Формат коммитов нужен не ради красоты: по типам собирают список изменений к релизу автоматически, а по областям фильтруют историю — `git log --grep="(auth)"` покажет всё, что делали с авторизацией.
$git status
Check
  • Сообщение начинается с типа
  • Область в скобках указана и взята из принятого набора
  • Первая строка короче 50 символов
3
Перед push поднять ветку над demo через rebase
bash
1git switch demo
2git pull origin demo
3git switch feature/your-name-of-feature
4git rebase demo

Что делает rebase: берёт твои коммиты и прикладывает их заново поверх свежего demo — как будто ты только что ответвился. История остаётся прямой, без лишнего коммита слияния.

Правило безопасности: rebase переписывает историю. Делай его только со своей веткой, которую никто больше не трогает. Никогда — с demo или main.

Если что-то пошло не так: git rebase --abort.

Why: Сравни с merge: он создаёт дополнительный коммит и ветвит историю. При десятке разработчиков история превращается в плетёнку, в которой невозможно найти, когда появилась ошибка. Rebase держит её линейной.
$git rebase demo
Check
  • Ветка поднята над свежим demo
  • Ты понимаешь, почему rebase нельзя делать с общими ветками
4
Первый PR: ветка в demo
bash
1git push origin feature/your-name-of-feature

Дальше на GitHub жмёшь New Pull Request и внимательно выбираешь направление:

  • basedemo (КУДА льём)
  • comparefeature/your-name-of-feature (ОТКУДА льём)

Затем описание и ревьюеры.

Если перепутать base и compare местами, PR предложит влить demo в твою ветку — то есть наоборот.

Why: На этом этапе код смотрят люди. Именно здесь ловятся ошибки, которые тесты не видят: непонятные имена, скопированный код, решения, которые через месяц придётся переписывать.
$git push origin feature/your-name-of-feature
Check
  • base = demo, compare = твоя ветка
  • В описании понятно, что и зачем сделано
  • Добавлены ревьюеры
5
Протестировать на demo

После мержа фича живёт в demo рядом с чужими. Это тот самый момент, ради которого вся схема и затевалась.

Why: Фича может работать идеально в одиночку и ломаться рядом с другой. Такие поломки не ловятся ни ревью, ни тестами отдельной ветки — только совместной проверкой.
Check
  • Фича проверена на demo вместе с остальными
6
Второй PR: demo в main

Когда на demo всё сошлось, создаётся второй pull request:

  • basemain
  • comparedemo

В описании перечисляются все изменения, которые уйдут в прод. Дальше — подтверждение от тимлида.

Этот PR делает не автор фичи, а тот, кто выпускает релиз.

Why: Второй PR — это граница между «работает у нас» и «работает у пользователей». Он даёт последнюю возможность остановиться и список того, что именно выкатывается.
Check
  • base = main, compare = demo
  • В описании перечислены все изменения релиза
  • Есть подтверждение ответственного
Почему ветку надо создавать от demo, а не от main?
С какими ветками НЕЛЬЗЯ делать rebase?
В PR выбрал base = своя ветка, compare = demo. Что произойдёт?
Когда эта схема нужна, а когда нет
СитуацияСхема
Один разработчик, выкатываешь когда готовоfeature/main, один PR
Несколько разработчиков, нужно проверять фичи вместеfeature/demomain
Есть отдельный стенд для тестированияточно с demo

Не бери сложную схему на вырост. Два PR на каждую правку в одиночном проекте — это ритуал, а не польза. Перейти от простой схемы к этой легко, обратно — тоже.