Работа с ветками в Git: создание, слияние, удаление

Полный цикл работы с веткой — от именования до удаления после мержа. С разбором реального случая, когда слияние упало в конфликты.

v1 0 stars 0 forks 0 watchers 1 branch 0 runs Public
mikicreated via APIv1
Работа с ветками

Ветка позволяет работать над изменением, не трогая то, что уже работает. Это главное, что даёт git: эксперимент становится бесплатным.

Порядок такой: обновиться → создать ветку → коммиты → синхронизация → push → pull request → мерж → удаление ветки.

Главное правило: ветку создавай до того, как начал менять файлы, а не после. Иначе легко обнаружить себя с коммитами не в той ветке.

Как называть ветки

Имя ветки читают другие люди — оно должно сразу говорить, что внутри.

ПрефиксДля чегоПримеры
feature/Новая функциональностьfeature/user-authentication, feature/payment-integration
fix/Исправление ошибкиfix/login-bug, fix/typo-in-readme
enhancement/Улучшение существующегоenhancement/performance-optimization
test/Тестыtest/add-unit-tests, test/integration-tests
docs/Документацияdocs/improve-readme, docs/api-documentation

Правила:

  • Префикс обязателен — по нему виден тип изменения без чтения кода.
  • Описывай, а не нумеруй. feature/new-style понятно, feature/task-42 — нет.
  • Слова через дефис: feature/new-style, а не feature/newstyle.
  • Без пробелов — имя с пробелом придётся каждый раз экранировать в терминале.

Цикл работы

1
Обновить основную ветку

Перед созданием ветки убедись, что у тебя свежий код.

bash
1git switch main
2git pull origin main

В старых статьях встретится git checkout main — это то же самое. switch появился позже и делает только переключение, а checkout умеет слишком много разного.

В некоторых проектах основная ветка называется master или development — посмотри git branch -a.

Why: Если ответвиться от устаревшего состояния, при слиянии получишь конфликты на ровном месте — в файлах, которые ты даже не трогал.
$git switch main && git pull origin main
Check
  • git status говорит, что ты на основной ветке
  • Ветка синхронизирована с сервером
2
Создать ветку

Флаг -c создаёт ветку и сразу переключает на неё.

bash
1git switch -c feature/new-feature

Старый вариант той же команды: git checkout -b feature/new-feature.

Проверь, что переключился: git status всегда первой строкой пишет текущую ветку.

Why: Ветка — это всего лишь указатель на коммит, несколько байт. Поэтому создавать их можно сколько угодно и ничего не копируется.
$git switch -c feature/new-feature
Check
  • git status показывает новую ветку
  • Имя ветки с префиксом и описывает задачу
3
Сделать коммиты
bash
1git add .
2git commit -m "feat: добавлена новая функция"

git add . добавляет всё сразу — удобно, но опасно: легко захватить лишнее. Сначала смотри git status, потом добавляй.

Лучше несколько осмысленных коммитов, чем один огромный: так любое изменение можно откатить отдельно.

Why: Сообщение коммита отвечает на «почему», а не на «что» — «что» всегда видно из диффа. Через год именно «почему» будет единственным, чего не хватает.
$git status
Check
  • В ветке есть минимум один коммит
  • В коммит не попало ничего лишнего
4
Периодически подтягивать основную веткуRecommended

Если работа идёт не один день, основная ветка уходит вперёд.

bash
1git switch main
2git pull origin main
3git switch feature/new-feature
4git merge main

Если возникнут конфликты, git о них скажет и остановится.

Why: Разбирать конфликты почастям гораздо легче, чем одним большим комом в конце. Чем дольше ветка живёт в отрыве, тем больнее будет слияние.
$git merge main
Check
  • Ветка содержит свежие изменения из основной
5
Отправить ветку на сервер
bash
1git push -u origin feature/new-feature

Флаг -u связывает локальную ветку с удалённой — дальше достаточно просто git push.

Why: Коммиты существуют только на твоём компьютере, пока не сделан push. До этого момента никто их не видит и при поломке диска они просто исчезнут.
$git push -u origin feature/new-feature
Check
  • Ветка видна на GitHub
  • git status пишет, что ветка отслеживает удалённую
6
Открыть pull request

На GitHub, GitLab или Bitbucket создай PR из своей ветки в основную.

В описании напиши, что сделано и зачем. Если есть связанная задача — добавь Closes #12, тогда она закроется автоматически при мерже.

Why: PR — единственное место, где изменение можно обсудить до того, как оно начало работать в проде. Плюс там же прогоняются проверки.
Check
  • PR открыт из ветки в основную, а не наоборот
  • В описании понятно, зачем это изменение

Удаление

7
Удалить ветку после мержа

После того как PR смержен:

bash
1git branch -d feature/new-feature # локально
2git push origin --delete feature/new-feature # на сервере
3git remote prune origin # почистить ссылки на удалённые

Важно про -d и -D: маленькая -d откажется удалять ветку, если её коммиты никуда не слиты. Большая -D удалит в любом случае. Пользуйся -d — это встроенная защита от потери работы.

Why: Неудалённые ветки накапливаются десятками, и через полгода непонятно, какие из них живые. `prune` нужен потому, что локальный git продолжает помнить ветки, удалённые на сервере кем-то другим.
$git branch -d feature/new-feature
Check
  • Локальная ветка удалена
  • Удалённая ветка удалена
  • git branch -a больше её не показывает
8
Вернуться на основную ветку и обновиться
bash
1git switch main
2git pull

Забыть этот шаг — классика: следующая ветка будет создана от устаревшего состояния, и круг замкнётся.

Why: Твой локальный main не знает, что PR смержен — слияние произошло на сервере. Пока не сделал pull, у тебя старая картина мира.
$git switch main && git pull
Check
  • Ты на основной ветке
  • Твоё изменение видно в локальной копии
Разбор случая: слияние упало в конфликты

Ниже — реальный случай, а не учебный пример. Задача была: слить фича-ветку в development, а потом development в main.

Первая часть прошла чисто. На второй git выдал:

code
1Auto-merging index.html
2CONFLICT (content): Merge conflict in index.html
3CONFLICT (content): Merge conflict in src/app/App.tsx
4CONFLICT (content): Merge conflict in src/widgets/footer/ui/Footer.tsx
5...
6Automatic merge failed; fix conflicts and then commit the result.

Что было сделано:

bash
1git merge --abort

Слияние отменили целиком и вернулись к исходному состоянию. main остался нетронутым.

Почему это правильное решение. Когда конфликтов семь штук в незнакомых файлах, разбирать их наскоро в терминале — верный способ сломать стабильную ветку. merge --abort — это кнопка «отмена», и о ней надо знать заранее.

Но вот что важнее. Задача так и осталась невыполненной: в main ничего не уехало. Конфликты не исчезли — их просто отложили. Разобрать их всᑑ равно придётся, и лучше через pull request: там видно каждый конфликт отдельно, есть история обсуждения и можно откатиться без последствий.

Вывод: локальный git merge в main — плохая идея в принципе. Он обходит ревью и проверки. Слияние в основную ветку должно идти через PR.

При слиянии получил семь конфликтов в незнакомых файлах. Что безопаснее всего сделать первым делом?
Чем отличается git branch -d от git branch -D?
Зачем нужен git remote prune origin?
Шпаргалка по командам
bash
1# где я и что происходит
2git status
3git branch -a
4
5# начать работу
6git switch main && git pull
7git switch -c feature/my-feature
8
9# сохранить
10git add .
11git commit -m "feat: описание"
12git push -u origin feature/my-feature
13
14# подтянуть чужие изменения
15git switch main && git pull
16git switch feature/my-feature && git merge main
17
18# если слияние пошло не так
19git merge --abort
20
21# убрать за собой
22git branch -d feature/my-feature
23git push origin --delete feature/my-feature
24git remote prune origin

Подробно и на русском — книга Pro Git, она бесплатная.