Обновить demo и ответвиться от неёChanged
1git switch demo
2git pull origin demo
3git switch -c feature/your-name-of-feature
Ключевое: ветка создаётся от demo, а не от main. Ответвишься от main — получишь конфликты со всем, что уже влили в demo до тебя. Перед созданием ветки проверь, что demo актуальна.
was: ```bash
git switch demo
git pull origin demo
git switch -c feature/your-name-of-feature
```
**Ключевое:** ветка создаётся от `demo`, а **не** от `main`. Ответвишься от `main` — получишь конфликты со всем, что уже влили в `demo` до тебя.
subtasks changed
git switch demo && git pull origin demoЗакоммитить измененияChanged
1git add .
2git commit -m "feat(cart): добавлено удаление товара из корзины"
Перед git add . всегда смотри git status — точка забирает всё, включая то, что ты не собирался коммитить. Проверь, что все изменения добавлены корректно.
was: ```bash
git add .
git commit -m "feat(cart): добавлено удаление товара из корзины"
```
Перед `git add .` всегда смотри `git status` — точка забирает всё, включая то, что ты не собирался коммитить.
subtasks changed
git statusПеред push поднять ветку над demo через rebaseChanged
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. Проверь, что после rebase все изменения на месте и нет конфликтов.
was: ```bash
git switch demo
git pull origin demo
git switch feature/your-name-of-feature
git rebase demo
```
**Что делает rebase:** берёт твои коммиты и прикладывает их заново поверх свежего `demo` — как будто ты только что ответвился. История остаётся прямой, без лишнего коммита слияния.
**Правило безопасности:** rebase **переписывает историю**. Делай его только со своей веткой, которую никто больше не трогает. Никогда — с `demo` или `main`.
Если что-то пошло не так: `git rebase --abort`.
subtasks changed
git rebase demoПервый PR: ветка в demoChanged
1git push origin feature/your-name-of-feature
Дальше на GitHub жмёшь New Pull Request и внимательно выбираешь направление:
- base —
demo (КУДА льём)
- compare —
feature/your-name-of-feature (ОТКУДА льём)
Затем описание и ревьюеры.
Если перепутать base и compare местами, PR предложит влить demo в твою ветку — то есть наоборот. Убедись, что PR создан корректно и все участники ревью добавлены.
was: ```bash
git push origin feature/your-name-of-feature
```
Дальше на GitHub жмёшь **New Pull Request** и внимательно выбираешь направление:
- **base** — `demo` (КУДА льём)
- **compare** — `feature/your-name-of-feature` (ОТКУДА льём)
Затем описание и ревьюеры.
Если перепутать base и compare местами, PR предложит влить `demo` в твою ветку — то есть наоборот.
subtasks changed
git push origin feature/your-name-of-featureПротестировать на demoChanged
После мержа фича живёт в demo рядом с чужими. Это тот самый момент, ради которого вся схема и затевалась. Проведи полное тестирование фичи в контексте других изменений.
was: После мержа фича живёт в `demo` рядом с чужими. Это тот самый момент, ради которого вся схема и затевалась.
subtasks changed
Второй PR: demo в mainChanged
Когда на demo всё сошлось, создаётся второй pull request:
- base —
main
- compare —
demo
В описании перечисляются все изменения, которые уйдут в прод. Дальше — подтверждение от тимлида.
Этот PR делает не автор фичи, а тот, кто выпускает релиз. Убедись, что все изменения в demo готовы к продакшену.
was: Когда на `demo` всё сошлось, создаётся второй pull request:
- **base** — `main`
- **compare** — `demo`
В описании перечисляются **все** изменения, которые уйдут в прод. Дальше — подтверждение от тимлида.
Этот PR делает не автор фичи, а тот, кто выпускает релиз.
subtasks changed
# Зачем промежуточная веткаRemoved
# Зачем промежуточная ветка
В простой схеме фичи льются сразу в `main`. Пока разработчик один, это работает. Как только появляется необходимость **проверить несколько фич вместе** до выкатки, нужна промежуточная ветка.
Здесь она называется `demo`. В других проектах встретишь `develop`, `development` или `staging` — суть одна.
```
feature/твоя-фича → demo → main
первый PR второй PR
(ревью) (релиз)
```
**Главное отличие от простой схемы:** два pull request вместо одного, и ветка ответвляется от `demo`, а не от `main`.
## Как оформлять коммитыRemoved
## Как оформлять коммиты
Полная форма сообщения выглядит так:
```
тип(область): описание в повелительном наклонении
```
Пять правил:
1. **Тип** — `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`.
2. **Повелительное наклонение** — «добавь», а не «добавил».
3. **Описывай ЧТО сделано, а не КАК.**
4. **Первая строка до 50 символов.**
5. **Подробности** — после пустой строки.
**Примеры по-русски:**
```
feat: добавлен модуль авторизации
fix: исправлен баг с регистрацией пользователя
docs: обновлена документация API
refactor: переработка модуля платежей
test: добавлены тесты для API эндпоинтов
chore: обновлены зависимости проекта
```
**Примеры по-английски:**
```
feat: add user authentication via JWT
fix: resolve database connection timeout
refactor: optimize course search algorithm
test: add integration tests for payment module
chore: upgrade FastAPI to v0.100.0
```
Язык выбирает команда — важно только, чтобы в одном проекте он был один.
## Что писать в скобочкахRemoved
## Что писать в скобочках
Скобки после типа — это **область изменения** (scope). Одно слово: какой части проекта касается коммит.
```
fix(git): успешный push не становится ошибкой
chore(deps): закрыты уязвимости ip-address и fast-uri
fix(ui): длинные названия больше не распирают мобильную вёрстку
feat(mcp): точечная правка списка
fix(cache): закрытие списка отзывает его у общего кеша сразу
feat(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(): ...` — ошибка, так не пишут.
**Ломающее изменение** помечается восклицательным знаком **после** скобок:
```
feat(api)!: убран устаревший эндпоинт /v1/users
```
Это сигнал: у того, кто пользуется твоим кодом, после обновления что-то сломается.
## Когда эта схема нужна, а когда нетRemoved
## Когда эта схема нужна, а когда нет
| Ситуация | Схема |
|---|---|
| Один разработчик, выкатываешь когда готово | `feature/` → `main`, один PR |
| Несколько разработчиков, нужно проверять фичи вместе | `feature/` → `demo` → `main` |
| Есть отдельный стенд для тестирования | точно с `demo` |
Не бери сложную схему на вырост. Два PR на каждую правку в одиночном проекте — это ритуал, а не польза. Перейти от простой схемы к этой легко, обратно — тоже.