Материал открыт для чтения

Войдите, чтобы сохранять прогресс и результаты.

Войти
Git: Основы

Ветки и merge до первой конфликтной ситуации

чтение ~6 минУрок 5 из 15

Ветки и merge до первой конфликтной ситуации

module git basics Image05

Ветка в Git - это подвижный указатель на коммит. Когда ты делаешь новый коммит, текущая ветка переезжает на него.

main
 |
 v
A -- B -- C

Если сейчас активна ветка main, и ты создаёшь новый коммит D, указатель main сдвинется:

A -- B -- C -- D
              main -> D

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


HEAD: где ты находишься

HEAD - это указатель на текущую позицию. В обычной работе HEAD указывает на текущую ветку, а ветка указывает на коммит.

HEAD -> main -> C

Посмотреть текущую ветку:

git branch
git status

В выводе git branch текущая ветка отмечена *.


Зачем нужны ветки

Ветки позволяют вести несколько линий работы:

  • main - стабильное состояние;
  • feature/login - новая функциональность;
  • feature/api - другая функциональность;
  • hotfix/nginx-config - срочное исправление.

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

С ветками можно изолировать работу:

main:          A -- B
                    \
feature/login:       C -- D

Пока фича не готова, main остаётся на коммите B.


Создание и переключение веток

Создать ветку, но не переключаться:

git branch feature/login

Переключиться на ветку:

git switch feature/login

Создать и сразу переключиться:

git switch -c feature/api

Вернуться в main:

git switch main

Старые материалы часто используют git checkout -b feature/api. Это тоже работает, но в новых курсах лучше привыкать к git switch: команда читается яснее и отвечает только за переключение веток.


Коммит в ветке

После переключения все новые коммиты будут двигать текущую ветку.

git switch -c feature/login
echo "# login module" > login.py
git add login.py
git commit -m "add login"

История:

main:          A -- B
                    \
feature/login:       C

Если теперь переключиться в main, файл login.py исчезнет из working tree, потому что в main такого файла ещё нет. Это нормально: Git приводит файлы на диске к состоянию выбранной ветки.


Что делает merge

git merge соединяет изменения из одной ветки в другую. Важно: merge выполняется в ветку, на которой ты сейчас находишься.

Чтобы слить feature/login в main:

git switch main
git merge feature/login

Сначала переходишь на ветку-приёмник, потом сливаешь ветку-источник.


Fast-forward merge

Fast-forward происходит, когда целевая ветка не имеет новых коммитов с момента создания feature-ветки.

До merge:

main:          A -- B
                    \
feature/login:       C

После fast-forward:

main:          A -- B -- C
feature/login:       ^

Git просто передвигает указатель main на коммит C. Отдельный merge commit не нужен, потому что истории не расходились в две активные линии.


Merge commit

Если обе ветки успели получить новые коммиты, Git создаёт merge commit.

main:          A -- B -- D
                    \    \
feature/login:       C --- M

Коммит M имеет двух родителей: один из main, другой из feature/login. Такой коммит фиксирует факт слияния.

Посмотреть структуру:

git log --oneline --graph --all --decorate
  • --oneline делает каждый коммит одной строкой;
  • --graph рисует ASCII-граф;
  • --all показывает все ветки;
  • --decorate показывает имена веток и тегов рядом с коммитами.

Удаление слитой ветки

После merge локальную feature-ветку часто удаляют:

git branch -d feature/login

-d удаляет только ветку, которая уже слита. Это защитный режим.

Если ветка не слита, Git предупредит. Есть принудительный режим:

git branch -D feature/experiment

Но на старте лучше не использовать -D без явной причины: можно потерять указатель на полезные коммиты.

Нельзя удалить ветку, на которой ты сейчас находишься. Сначала переключись:

git switch main
git branch -d feature/login

Когда возникает конфликт

Merge conflict возникает, когда Git не может автоматически совместить изменения. Чаще всего это одна и та же строка одного файла, изменённая по-разному в двух ветках.

Пример:

main меняет app.txt:    mode=production
branch-b меняет там же: mode=debug

Git не знает, какой вариант правильный, поэтому останавливает merge и просит человека принять решение.


Как выглядит конфликт

В конфликтном файле появляются маркеры:

<<<<<<< HEAD
версия из текущей ветки
=======
версия из ветки, которую сливаешь
>>>>>>> branch-b

HEAD - это текущая ветка, то есть ветка-приёмник merge. Нижняя часть - incoming change из ветки, которую ты сливаешь.

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

Например, если нужно оставить только Resolved version.

файл после правки должен содержать именно это, без <<<<<<<, ======= и >>>>>>>.


Порядок разрешения конфликта

Типичный порядок:

git status
# открыть конфликтный файл и отредактировать
git add app.txt
git commit -m "resolve conflict"

Что происходит:

  1. git status показывает, какие файлы конфликтуют.
  2. Ты редактируешь файл до правильного финального состояния.
  3. git add app.txt сообщает Git, что конфликт в этом файле решён.
  4. git commit завершает merge и создаёт merge commit.

После завершения полезно посмотреть граф:

git log --oneline --graph --all

Конфликт - не ошибка Git. Это ситуация, где автоматическое объединение было бы опаснее, чем остановка и ручной выбор.

Материал изучен?

Войдите, чтобы сохранить прогресс и перейти к практической лаборатории.

Войти и продолжить