Ветка — параллельная история
Ветка в Git — это отдельная линия истории проекта: в ней можно делать коммиты, а рабочая версия в ветке main в это время остаётся нетронутой. Вы создадите ветку feature/projects, добавите в ней страницу проектов и научитесь переключаться между ветками командой git switch.
Отменять ошибки и доставать «потерянные» коммиты через reflog вы уже умеете. Но экспериментировать прямо в рабочей версии всё равно неуютно: пока новая страница не готова, сайт в main должен оставаться целым. Для этого и придуманы ветки.
Простыми словами
Вы пишете книгу и хотите переписать главу. Чистовик не трогаете, пробуете в черновике. Получилось — переносите главу в книгу, нет — выбрасываете черновик. Ветка — такой черновик для всего проекта.
Официальный термин
В документации ветка (branch) — это подвижный указатель на коммит: крошечная запись с хешем последнего коммита линии. При новом коммите указатель текущей ветки сам передвигается на него. Поэтому ветка создаётся мгновенно и почти ничего не весит.
Частая путаница: ветка и копия папки
Многие сначала делают «ветки» руками: копируют папку в portfolio-new или portfolio-final2. Ветка Git — не копия: папка проекта остаётся одна, а при переключении Git сам подменяет в ней файлы. Никаких дублей на диске.
Где тут HEAD
HEAD вы уже встречали, когда смотрели старый коммит: это отметка «где вы сейчас». Обычно HEAD указывает не на коммит, а на ветку: «я на ветке main». А ветка указывает на свой последний коммит:
HEAD --> main --> 5acc5ae (Revert "Поменять цвет фона")
Что на схеме: вы стоите на ветке main, а main смотрит на коммит 5acc5ae — последний коммит прошлого модуля. Сделаете новый коммит — main передвинется на него, а HEAD так и останется на main.
git branch и git switch -c
Сначала посмотрим, какие ветки уже есть. Выполните в папке проекта:
$ git branch
* main
Разбор по строкам
* main— ветка пока одна,main. Звёздочка отмечает текущую ветку, на которую смотрит HEAD.
Ветка main у вас с первого коммита. Создадим новую ветку и сразу перейдём на неё. Команда git switch значит «переключиться», а флаг -c (от create) — «сначала создать»:
$ git switch -c feature/projects
Switched to a new branch 'feature/projects'
$ git branch
* feature/projects
main
Разбор по строкам
Switched to a new branch 'feature/projects'— «переключились на новую веткуfeature/projects».* feature/projects— звёздочка переехала: теперь вы на новой ветке.main—mainникуда не делась. Сейчас обе ветки указывают на один и тот же коммит5acc5ae: новая ветка начинается там, где вы стояли.
Вернуться на существующую ветку — та же команда, но без -c: git switch main. Git ответит Switched to branch 'main'. Есть и команда git branch имя — она создаёт ветку, но не переходит на неё. Удобнее сразу git switch -c.
В старых статьях: git checkout
В старых статьях и ответах вы встретите git checkout -b feature/projects — это то же, что git switch -c feature/projects, а git checkout main — то же, что git switch main. checkout работает, но умеет слишком много разного (и ветки, и файлы), поэтому в курсе — switch.
Спасти коммиты из detached HEAD можно веткой
Помните режим detached HEAD, когда вы смотрели старый коммит? Если вы успели там что-то закоммитить, эти коммиты не принадлежат ни одной ветке. Спасение — создать ветку прямо в этом состоянии: git switch -c experiment. Коммиты окажутся в ветке experiment, и их уже не потерять.
Уже ушли на main? Найдите хеш коммита в git reflog и создайте ветку на нём: git switch -c experiment <хеш>.
Коммиты в ветке
Вы на ветке feature/projects. Создайте в VS Code рядом с index.html новый файл projects.html — это отдельная страница проектов: та же шапка head, заголовок, две карточки-абзаца и ссылка обратно на главную.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Алекс Иванов - Мои проекты</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Мои проекты</h1>
<p><strong>Сайт-визитка.</strong> Моя первая страница на HTML и CSS, история ведётся в Git.</p>
<p><strong>Список дел.</strong> Маленькое приложение: добавить задачу и отметить её сделанной.</p>
<p><a href="index.html">На главную</a></p>
</body>
</html>
Коммит в ветке делается точно так же, как раньше:
$ git status
On branch feature/projects
Untracked files:
(use "git add <file>..." to include in what will be committed)
projects.html
nothing added to commit but untracked files present (use "git add" to track)
$ git add projects.html
$ git commit -m "Добавить страницу проектов"
[feature/projects 294653e] Добавить страницу проектов
1 file changed, 14 insertions(+)
create mode 100644 projects.html
Разбор по строкам
On branch feature/projects— первая строкаgit statusвсегда называет текущую ветку. Привыкайте смотреть на неё.[feature/projects 294653e]— коммит попал в веткуfeature/projects, его хеш294653e(у вас будет свой).
$ git log --oneline
294653e (HEAD -> feature/projects) Добавить страницу проектов
5acc5ae (main) Revert "Поменять цвет фона"
875cb0a Поменять цвет фона
...
Разбор по строкам
(HEAD -> feature/projects)— HEAD указывает на веткуfeature/projects, а она — на новый коммит. Ветка передвинулась сама.(main)—mainосталась на5acc5ae: ваша новая работа её не тронула.
Переключение меняет рабочую папку
Теперь самое интересное. Перейдите на main и посмотрите на файлы:
$ git switch main
Switched to branch 'main'
$ ls
README.md
index.html
notes
style.css
$ git switch feature/projects
Switched to branch 'feature/projects'
$ ls
README.md
index.html
notes
projects.html
style.css
Разбор по строкам
- После
git switch mainфайлаprojects.htmlнет: в веткеmainего не существует, и Git убрал его из рабочей папки. - Файл не удалён — он хранится в коммите
294653e. Послеgit switch feature/projectsон снова на месте. notes— ваши личные черновики. Их нет в Git (они в.gitignore), поэтому Git не трогает их ни в одной ветке.
Так и работает переключение: Git приводит рабочую папку к последнему коммиту выбранной ветки.
Видим ветки в истории
Обычный git log показывает только текущую ветку. Флаг --graph рисует линии, --all берёт все ветки. Перейдите на main и выполните:
$ git switch main
Switched to branch 'main'
$ git log --oneline --graph --all
* 294653e (feature/projects) Добавить страницу проектов
* 5acc5ae (HEAD -> main) Revert "Поменять цвет фона"
* 875cb0a Поменять цвет фона
* 746ac3d Добавить описание сайта
* 12d081f Добавить .gitignore
* 284ecf7 Исправить опечатку в заголовке
* cb00bb8 Добавить раздел «Мои проекты»
* f58d529 Добавить README
* 8c23940 Добавить стили
* 027a150 Добавить главную страницу
Разбор по строкам
- Каждая
*— коммит, новые сверху. (feature/projects)у верхнего коммита — ветка ушла на коммит вперёд;(HEAD -> main)— вы наmain, она на шаг позади.- Линия пока прямая: в
mainпосле развилки ничего не появлялось. «Вилка» на графе появится, когда коммиты будут в обеих ветках.
... --- 875cb0a --- 5acc5ae --- 294653e
^ ^
main feature/projects
Что на схеме: коммиты одни на всех, а ветки — просто метки, приклеенные к разным коммитам одной цепочки.
Как называть ветки
Имя ветки пишут для людей. Частая договорённость — приставка по смыслу и короткое описание после косой черты:
feature/…— новая возможность:feature/projects,feature/footer;fix/…— исправление:fix/projects-link;- после косой — коротко, латиницей, строчными буквами, слова через дефис;
- без пробелов: пробел в имени ветки Git не разрешит.
$ git switch -c "my branch"
fatal: 'my branch' is not a valid branch name
hint: See `man git check-ref-format`
hint: Disable this message with "git config advice.refSyntax false"
Разбор по строкам
fatal: 'my branch' is not a valid branch name— «недопустимое имя ветки»: мешает пробел. Строкиhint:подсказывают, где прочитать правила имён и как отключить подсказку.
Косая черта в feature/projects — часть имени, а не папка в проекте: никакой папки feature в portfolio не появится. Подробно о ветках — в документации git switch и git branch.
Практика у себя
Если ветку и страницу вы уже создали, пока читали, просто сверьтесь с шагами.
Шаг 1. Откройте терминал в папке проекта и убедитесь, что вы на main и всё закоммичено:
$ cd ~/projects/portfolio
$ git status
On branch main
nothing to commit, working tree clean
Шаг 2. Создайте ветку и проверьте, что вы на ней:
$ git switch -c feature/projects
Switched to a new branch 'feature/projects'
$ git branch
* feature/projects
main
Шаг 3. Создайте projects.html с кодом из раздела «Коммиты в ветке». git status покажет его в Untracked files.
Шаг 4. Закоммитьте страницу:
$ git add projects.html
$ git commit -m "Добавить страницу проектов"
[feature/projects 294653e] Добавить страницу проектов
1 file changed, 14 insertions(+)
create mode 100644 projects.html
Шаг 5. Перейдите на main и выполните ls — projects.html исчезнет. Вернитесь на feature/projects — появится снова.
Шаг 6. Вернитесь на main и посмотрите на граф:
$ git switch main
Switched to branch 'main'
$ git log --oneline --graph --all
* 294653e (feature/projects) Добавить страницу проектов
* 5acc5ae (HEAD -> main) Revert "Поменять цвет фона"
* 875cb0a Поменять цвет фона
* 746ac3d Добавить описание сайта
* 12d081f Добавить .gitignore
* 284ecf7 Исправить опечатку в заголовке
* cb00bb8 Добавить раздел «Мои проекты»
* f58d529 Добавить README
* 8c23940 Добавить стили
* 027a150 Добавить главную страницу
Проверьте себя
git branchпоказывает две ветки:feature/projectsиmain, звёздочка уmain.- В
git log --oneline --graph --allверхний коммит «Добавить страницу проектов» помечен(feature/projects), а(HEAD -> main)стоит на «Revert "Поменять цвет фона"». - На
mainфайлаprojects.htmlв папке нет, наfeature/projects— есть. git statusнаmain:nothing to commit, working tree clean.
Частые ошибки
Git не даёт переключиться: would be overwritten. Вы поправили файл, не закоммитили и пытаетесь уйти в ветку, где этот файл другой:
$ git switch main
error: Your local changes to the following files would be overwritten by checkout:
style.css
Please commit your changes or stash them before you switch branches.
Aborting
Разбор по строкам
error: Your local changes ... would be overwritten by checkout— «ваши локальные изменения будут затёрты», а строкой ниже — файл, который мешает (style.css). Словоcheckout— наследие старой команды,git switchпишет так же.Please commit your changes or stash them ...— «закоммитьте изменения или уберите их в stash».Aborting— переключение отменено, ничего не потеряно.
Git защищает вашу несохранённую работу. Выхода два: закоммитить правку или временно спрятать её командой git stash — её разберём чуть позже в этом модуле. А если файл в обеих ветках одинаковый, Git переключится и перенесёт правку с собой.
Коммит не в ту ветку. Забыли git switch -c и закоммитили новую страницу прямо в main. Пока коммит есть только у вас на компьютере, это легко поправить: создать ветку на этом коммите, вернуть main на шаг назад и перейти на новую ветку.
$ git branch feature/projects
$ git reset --hard HEAD~1
HEAD is now at 5acc5ae Revert "Поменять цвет фона"
$ git switch feature/projects
Switched to branch 'feature/projects'
Разбор по строкам
git branch feature/projects— ветка запоминает текущий коммит со страницей; вы остаётесь наmain.git reset --hard HEAD~1—mainвозвращается на коммит назад (HEAD is now at ...), а страница остаётся в новой ветке.
Осторожно с reset --hard
Перед git reset --hard убедитесь, что git status чистый: незакоммиченные правки эта команда уничтожит без возврата.
«Файл пропал». Вы открыли проект и не нашли projects.html. Скорее всего, вы на другой ветке. Первым делом — git status или git branch: какая ветка текущая. Перейдите на нужную, и файл вернётся.
Опечатка в имени ветки. git switch feature/projets ответит fatal: invalid reference: feature/projets — такой ветки нет. Посмотрите точное имя в git branch.
Что важно запомнить
- Ветка — подвижный указатель на коммит, а не копия папки. Папка одна, Git подменяет в ней файлы.
- HEAD указывает на текущую ветку, ветка — на свой последний коммит. Коммит двигает текущую ветку вперёд.
git branch— список веток,git switch -c имя— создать и перейти,git switch имя— перейти.git log --oneline --graph --allпоказывает все ветки и где какая стоит.- Имена:
feature/…,fix/…, латиница, без пробелов. - Переключаться лучше с чистым
git status, иначе Git может не пустить (would be overwritten).
Страница проектов готова, но живёт только в ветке feature/projects: на главной её нет. Как перенести работу из ветки в main — слияние веток, в следующем уроке.