Что такое HEAD
HEAD в Git – это указатель на то место, где ты сейчас находишься.
Чаще всего HEAD указывает не прямо на коммит, а на текущую ветку. А уже ветка указывает на последний коммит.
HEAD -> main -> C
Это значит:
- сейчас ты на ветке
main - ветка
mainуказывает на последний коммитC
Когда ты делаешь новый коммит, двигается ветка, а HEAD просто остается привязанным к ней.
HEAD -> main -> D
Что такое detached HEAD
detached HEAD – это состояние, когда HEAD указывает не на ветку, а прямо на конкретный коммит.
HEAD -> a1b2c3d
Обычно это происходит, если перейти на коммит напрямую.
git checkout a1b2c3d
или так:
git switch --detach a1b2c3d
Что это означает на практике:
- ты смотришь состояние проекта в старом коммите
- ты не находишься на ветке
- если сделать новый коммит, он не будет привязан к какой-либо ветке
A - B - C <- main
\
D <- HEAD
Коммит D существует, но ветка на него не смотрит. Если потом переключиться обратно на main, этот коммит можно легко потерять из виду. Он не пропадет мгновенно, но станет “висячим”.
Если начал что-то менять и хочешь сохранить результат – создай ветку от старого коммита:
git switch -c new-branch
Тогда будет уже нормально:
HEAD -> new-branch
Что такое checkout
checkout – это старая универсальная команда Git. Она умеет сразу несколько вещей, из-за этого часто и путала людей.
Через checkout можно:
- переключаться между ветками
- переходить на коммиты
- создавать ветки
- восстанавливать файлы
Примеры:
git checkout main
git checkout a1b2c3d
git checkout -b feature-login
То есть одна команда делала слишком много всего. Такая себе гит-мясорубка.
Что делает git checkout a1b2c3d
Команда:
git checkout a1b2c3d
делает вот что:
- берет состояние проекта из коммита
a1b2c3d - переключает рабочую директорию на это состояние
- переводит тебя в режим
detached HEAD
То есть ты переходишь на старый коммит напрямую, а не через ветку.
Как переключиться на старый коммит
Есть несколько способов.
Старый синтаксис:
git checkout a1b2c3d
Новый синтаксис:
git switch --detach a1b2c3d
Если хочешь не просто посмотреть старый коммит, а начать от него работать дальше, лучше сразу создать ветку:
git switch -c old-fix a1b2c3d
Старым синтаксисом это выглядело бы так:
git checkout -b old-fix a1b2c3d
Что такое switch
switch – это более новый синтаксис Git для переключения веток и состояний HEAD.
Он появился, потому что checkout был слишком перегруженным. Поэтому Git начали разделять на более понятные команды:
git switch– для переключения веток и коммитовgit restore– для восстановления файлов
Примеры switch:
git switch main
git switch -c feature-login
git switch --detach a1b2c3d
Да, по сути switch – это новый, более понятный синтаксис именно для переключения веток и состояний HEAD.
Разница между checkout и switch
checkout:
- старая команда
- умеет слишком много разного
- может путать
switch:
- новая команда
- отвечает именно за переключение
- читается понятнее
Но знать checkout все равно надо, потому что его до сих пор полно в старых гайдах, статьях и чужих проектах.
Полезные варианты перехода на старые коммиты
По хэшу коммита:
git switch --detach a1b2c3d
На один коммит назад:
git switch --detach HEAD~1
На два коммита назад:
git switch --detach HEAD~2
На тег:
git switch --detach v1.0.0
Если надо сразу начать новую ветку от старого состояния:
git switch -c my-branch a1b2c3d
Как понять, где ты сейчас
Проверить текущее состояние можно так:
git status
Если ты на ветке, увидишь что-то вроде:
On branch main
Если ты в detached HEAD, Git напишет примерно так:
HEAD detached at a1b2c3d
Как выйти из detached HEAD
Если ты просто смотрел старый коммит и хочешь вернуться обратно:
git switch main
Если ты в detached HEAD уже сделал полезные коммиты и не хочешь их потерять:
git switch -c save-my-work
Короткая шпаргалка
Перейти на ветку:
git checkout main
git switch main
Перейти на конкретный коммит:
git checkout a1b2c3d
git switch --detach a1b2c3d
Создать новую ветку и перейти на нее:
git checkout -b feature
git switch -c feature
Создать ветку от старого коммита:
git checkout -b old-fix a1b2c3d
git switch -c old-fix a1b2c3d
Самая практичная мысль
Если хочешь просто посмотреть старый коммит:
git switch --detach <commit>
Если хочешь от него работать дальше:
git switch -c <new-branch> <commit>
Вот это уже нормальная, безопасная практика без шансов случайно потерять свои коммиты.