GIT: HEAD, checkout, switch
Glossary overview

GIT: HEAD, checkout, switch

Что такое 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>

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