Урок 5. Ветки: branch, switch, merge
Ветка — отдельная линия работы. Пока вы пробуете новую идею в своей ветке, основная main остаётся рабочей. Получилось — ветку сливают с основной, не получилось — просто удаляют. Ветки в Git создаются мгновенно и почти ничего не занимают, поэтому их заводят на каждую задачу.
Как это устроено: ветка — это просто указатель на последний коммит своей линии. Новый коммит сдвигает указатель вперёд. А HEAD показывает, на какой ветке вы сейчас.
Список веток
$ 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 — строка снова появится.
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. Новых коммитов не возникло.
Коммит слияния
Если за это время коммиты появились и в 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 Первый коммит: список делЕсли обе ветки поменяли одни и те же строки, 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, где регистр в именах файлов обычно не различается, такие ветки путаются.
Частые ошибки
- Работа не в той ветке. Перед началом задачи посмотрите
git status— первая строкаOn branch …называет текущую ветку. Если коммит ушёл не туда, его можно перенести, но проще проверять заранее. - Слияние «не в ту сторону».
git merge shopизmainприноситshopвmain. Изshopта же команда сmainпринесётmainвshop. fatal: invalid referenceприgit switch имя— такой ветки нет: проверьте имя черезgit branch -a.
Коротко
git branch— список веток,*— текущая.git switch -c имя— создать ветку и перейти;git switch имя— перейти (старый способ —git checkout).git merge ветка— слить ветку в текущую: перемоткой (fast-forward) или коммитом слияния.git branch -d имя— удалить слитую ветку,-D— удалить в любом случае.git log --oneline --graph --all— история всех веток.