Git ветки: создание, слияние и конфликты
Что такое ветка в Git
Ветка в Git — это просто текстовый файл в .git/refs/heads/, содержащий хеш одного коммита. Всё. Никакого копирования файлов, никаких дубликатов — только указатель.
Когда ты делаешь git commit, Git создаёт объект коммита и перезаписывает файл текущей ветки новым хешем. Создание ветки занимает микросекунды и не зависит от размера репозитория.
.git/refs/heads/main → "a1b2c3d4e5f6..."
.git/refs/heads/feature → "7g8h9i0j1k2l..."
HEAD — где ты сейчас
HEAD — специальный указатель, который всегда знает текущую ветку:
HEAD → main → a1b2c3
При переключении ветки Git обновляет HEAD и восстанавливает рабочий каталог до состояния целевого коммита. При новом коммите двигаются и HEAD, и текущая ветка вместе.
Создание и переключение веток
git branch feature # создать ветку
git switch feature # переключиться на ветку
git switch -c feature # создать + сразу переключиться
git branch # список всех веток (* = текущая)
git branch -d feature # удалить после merge
git branch -D feature # удалить принудительно
git switch — современная замена git checkout. Checkout исторически делал слишком много разных вещей. switch занимается только переключением веток.
Как работает merge
Когда ветки сходятся, возникает два сценария:
Fast-forward
Если main не двигался, пока ты работал в feature:
До: main → C1 → C2 → C3 ← feature
↑
(обе точат на C3)
git switch main && git merge feature
После: main → C1 → C2 → C3 → C4 → C5 ← main, feature
Git просто перемещает указатель main вперёд — «перемотка». Новых коммитов не создаётся.
Три-точечный merge (merge commit)
Если main тоже получил новые коммиты, пока существовала feature:
До:
main: C1 → C2 → C3 → C5
↓
feature: C3 → C4
После git merge feature:
main: C1 → C2 → C3 → C5 → C6 (merge commit)
↓ ↑
feature: C3 → C4 ──┘
Создаётся merge-коммит (C6) с двумя родителями. История отражает, что работа шла параллельно.
Флаг --no-ff
git merge --no-ff feature -m "feat: добавил поиск"
Принудительно создаёт merge-коммит даже при fast-forward. Делает в истории явный «пакет» изменений — видно, где заканчивается одна задача и начинается другая.
Конфликты
Конфликт возникает, когда две ветки изменили одни и те же строки одного файла. Git не выбирает сам — вставляет маркеры и останавливается:
<<<<<<< HEAD
version: "2.0",
=======
version: "2.1-beta",
>>>>>>> feature
Разрешение:
- Открыть файл, найти маркеры
- Оставить нужный вариант, убрать маркеры (
<<<<<<<,=======,>>>>>>>) git add имя-файлаgit commit
git status # покажет conflicted файлы
git merge --abort # отменить merge, вернуться назад
VS Code и IntelliJ показывают конфликты графически: кнопки «Accept Current», «Accept Incoming», «Accept Both» прямо над каждым конфликтным блоком.
Типичный рабочий процесс
# Начинаем новую задачу
git switch main
git pull origin main # берём последнее с сервера
git switch -c feature/search # создаём ветку
# Работаем
git add .
git commit -m "feat: добавил строку поиска"
git commit -m "feat: добавил фильтрацию результатов"
# Перед merge — обновляем main в своей ветке
git fetch origin
git merge origin/main # или git rebase origin/main
# Сливаем
git switch main
git merge --no-ff feature/search -m "feat: поиск"
git branch -d feature/search
# Отправляем
git push origin main
Советы
Называй ветки по смыслу. feature/user-auth, fix/login-crash, refactor/db-layer — сразу понятно, что внутри.
Мержи main в свою ветку, пока работаешь. Ветка живёт 3 дня — обновляй main каждый день. Маленькие конфликты лучше одного большого в конце.
Используй Pull Request. В командных проектах ветки не мержатся напрямую. Создаёшь PR/MR в GitHub/GitLab, коллеги смотрят diff и оставляют комментарии. После апрува — merge кнопкой.
Fast-forward vs merge commit. В личных проектах fast-forward даёт чистую историю. В командных — --no-ff позволяет понять, где была отдельная задача.
Команды для ежедневной работы
git branch # список веток
git switch -c feature/name # создать и переключиться
git merge feature # слить ветку в текущую
git merge --no-ff feature # слить с merge-коммитом
git merge --abort # отменить merge
git log --all --oneline --graph # граф всех веток
git branch -d feature # удалить ветку после merge
Что дальше
- Что такое ветки и зачем они нужны — интерактивная визуализация
- Слияние веток и конфликты — merge в деталях
- Конфликты слияния — пошаговое разрешение