Глиф Учебники

Урок 5. Ветки: branch, switch, merge

Курс «Git» · урок 5 из 9 · 4 минуты чтения

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

Как это устроено: ветка — это просто указатель на последний коммит своей линии. Новый коммит сдвигает указатель вперёд. А HEAD показывает, на какой ветке вы сейчас.

git switch -c shop main shop HEAD 1bd6527 3a2e9d2 git commit -am "Добавлен сыр" main shop HEAD 1bd6527 3a2e9d2 3caf46b новый
Новая ветка shop указывает на тот же коммит, что и main, а после коммита в ней сдвигается вперёд вместе с HEAD, пока main остаётся на месте.

Список веток

Терминал
$ git branch
* main

Звёздочка — текущая ветка. Пример продолжает репозиторий todo из урока Первый репозиторий.

Создать ветку и перейти в неё

Терминал
$ git switch -c shop
Switched to a new branch 'shop'

git switch -c имя создаёт ветку от текущего коммита и сразу переключается на неё. По отдельности: git branch shop — создать, git switch shop — перейти.

В старых версиях Git и во многих инструкциях то же делает git checkout: git checkout shop — перейти, git checkout -b shop — создать и перейти. Эти команды работают и сейчас. git switch появился в Git 2.23 и нужен только для веток, поэтому с ним труднее ошибиться.

Работа в ветке

Сделайте в ветке коммит, как обычно:

Терминал
$ echo "- купить сыр" >> README.md
$ git commit -am "Добавлен сыр"
[shop 3caf46b] Добавлен сыр
 1 file changed, 1 insertion(+)

Теперь вернитесь в main и откройте README.md: строки про сыр там нет. При переключении Git меняет файлы в рабочей папке так, как они выглядят в выбранной ветке. Вернётесь в shop — строка снова появится.

Bash
git switch main

Если в рабочей папке есть незакоммиченные правки, которые помешают переключению, Git откажется и напишет Your local changes to the following files would be overwritten by checkout. Сделайте коммит или отложите правки через git stash, а потом переключайтесь.

Слить ветку: git merge

Сливают всегда в текущую ветку. Чтобы перенести работу из shop в main, перейдите в main и выполните git merge shop:

Терминал
$ git switch main
Switched to branch 'main'
$ git merge shop
Updating 3a2e9d2..3caf46b
Fast-forward
 README.md | 1 +
 1 file changed, 1 insertion(+)

Fast-forward («перемотка вперёд») — самый простой случай: в main с момента ответвления ничего не появилось, и Git просто сдвинул указатель main на последний коммит shop. Новых коммитов не возникло.

git merge shop из ветки main main main shop HEAD 1bd6527 3a2e9d2 3caf46b Добавлен сыр новых коммитов нет после ответвления в main ничего не появилось
При перемотке git merge shop просто сдвигает указатель main с 3a2e9d2 на последний коммит shop 3caf46b, и новых коммитов не появляется.

Коммит слияния

Если за это время коммиты появились и в main, перемотать нельзя — линии разошлись. Тогда Git создаёт коммит слияния (merge commit), у которого два родителя:

Терминал
$ git merge shop
Merge made by the 'ort' strategy.
 README.md | 1 +
 1 file changed, 1 insertion(+)

Перед этим Git откроет редактор с готовым сообщением Merge branch 'shop' — сохраните и закройте его. Не хотите редактора — git merge --no-edit shop. Слова 'ort' strategy — название способа слияния, в старых версиях там 'recursive'.

Как выглядит такая история:

Терминал
$ git log --oneline --graph --all
*   a9f611f (HEAD -> main) Merge branch 'shop'
|\
| * 3caf46b (shop) Добавлен сыр
* | fea6be9 Добавлены заметки
|/
* 3a2e9d2 Добавлен первый пункт
* 1bd6527 Первый коммит: список дел
shop 3caf46b Добавлен сыр 1bd6527 3a2e9d2 fea6be9 Добавлены заметки a9f611f Merge branch 'shop' main HEAD коммит слияния: два родителя
Коммит слияния a9f611f продолжает и main, и shop: у него два родителя — fea6be9 из main и 3caf46b из shop, и на него теперь указывает main.

Если обе ветки поменяли одни и те же строки, Git не знает, какой вариант верный, и останавливается с конфликтом. Это обычная ситуация, о ней — урок Конфликты слияния.

Удалить ветку

Ветка слита — она больше не нужна:

Терминал
$ git branch -d shop
Deleted branch shop (was 3caf46b).

Коммиты при этом не пропадают: они уже в main. Если ветка не слита, -d откажется (not fully merged) — так Git защищает от потери работы. Удалить всё равно — git branch -D shop. Подробнее, и как удалить ветку на сервере, — в справке Как удалить ветку.

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

Имя ветки — без пробелов, обычно латиницей: shop, fix-login, feature/search. Косая черта допустима и помогает группировать: feature/… — новые возможности, fix/… — исправления. Пишите имена строчными буквами: Shop и shop Git считает разными ветками, а в Windows и macOS, где регистр в именах файлов обычно не различается, такие ветки путаются.

Частые ошибки

Коротко

Проверьте себя

1. Что делает git switch -c fix?
2. Вы в ветке main. Что сделает git merge shop?
3. Что такое fast-forward?
4. Почему git branch -d отказался удалить ветку?