← Назад к вопросам

Что такое HEAD в Git?

1.0 Junior🔥 161 комментариев
#Другое

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# HEAD в Git: подробное объяснение

Определение

HEAD — это специальный указатель (reference) в Git, который указывает на текущий коммит, на котором вы находитесь. Проще говоря, это ваше текущее место в истории проекта.

Аналогия

Представь историю коммитов как список страниц в книге:

Стр.1 (первый коммит) → Стр.2 → Стр.3 → Стр.4 → Стр.5
                                              ^
                                            HEAD (вы здесь)

Где находится HEAD, оттуда начинаются новые изменения.

Где хранится информация о HEAD?

Гит хранит информацию о HEAD в файле .git/HEAD:

$ cat .git/HEAD
ref: refs/heads/main

Это говорит: "HEAD указывает на ветку main".

А сама ветка main — это файл, который содержит хеш коммита:

$ cat .git/refs/heads/main
f2662fbc7d9e5f1a2c3d4e5f6a7b8c9d0e1f2a3b

HEAD при работе с ветками

Детач HEAD (detached HEAD)

Обычно HEAD указывает на ветку. Но если вы checkout-ите конкретный коммит, HEAD "отсоединяется" от ветки:

# Обычно: HEAD → main → коммит f266
$ git checkout f266

# Теперь: HEAD → (коммит f266 напрямую)
# .git/HEAD содержит не "ref: refs/heads/...", а просто хеш
$ cat .git/HEAD
f2662fbc7d9e5f1a2c3d4e5f6a7b8c9d0e1f2a3b

Это может быть опасно: если вы делаете коммиты в detached state, потом checkout-ите другую ветку, эти коммиты могут потеряться.

$ git checkout main
WARNING: you are leaving 1 commit behind, not connected to any branch

Крепёж HEAD к ветке

Обычно HEAD привязан к текущей ветке:

$ git branch
* main          # * означает, что HEAD указывает на main
  feature/auth
  bugfix/login

$ git checkout feature/auth
$ git branch
  main
* feature/auth  # Теперь HEAD указывает сюда

HEAD при операциях слияния

Обычное слияние

# Находимся на main, HEAD указывает на main
$ git merge feature/auth

# Создаётся merge-коммит
# HEAD остаётся на main, но main теперь указывает на новый коммит

Merge conflict

Когда есть конфликт, HEAD указывает на "наш" вариант:

$ git merge feature/auth
Conflict in file.txt

<<<<<<< HEAD           # Наша версия (текущая ветка)
используй Hibernate
=======
используй JPA         # Их версия (mergeable ветка)
>>>>>>> feature/auth

Относительные ссылки (^ и ~)

Вы можете ссылаться на коммиты относительно HEAD:

HEAD^ (parent)

# Коммит, на который сейчас указывает HEAD
$ git show HEAD

# Родительский коммит
$ git show HEAD^
# или
$ git show HEAD~1

# Второй родитель при merge (если было слияние двух веток)
$ git show HEAD^2

HEAD~ (первый предок)

# Один коммит назад
$ git show HEAD~

# Два коммита назад
$ git show HEAD~2

# Три коммита назад
$ git show HEAD~3

Разница между ^ и ~

# При merge коммите:
#     HEAD
#      /  \
#    ^1   ^2   (оба родителя)
#     |     |  
#   HEAD~   HEAD~2  (второй родитель)

# Практический пример:
$ git log --oneline
f266 Merge branch feature/auth (merge коммит с 2 родителями)
e456 Add auth
d789 Fix login

$ git show HEAD^1   # первый родитель merge
$ git show HEAD^2   # второй родитель merge (ветка feature/auth)

HEAD в реальных сценариях

Отмена последнего коммита

# Отмена с сохранением изменений
$ git reset --soft HEAD~
# HEAD указывает на предыдущий коммит, но файлы остаются изменённые

# Полная отмена
$ git reset --hard HEAD~
# HEAD указывает на предыдущий коммит, файлы восстанавливаются

Просмотр изменений с момента ветвления

# Вы на feature ветке
# Какие коммиты были с момента создания feature?
$ git log main..HEAD
# или
$ git log main..feature

Rebase

$ git rebase main
# HEAD перепривязывается к главной ветке
# Все коммиты feature ветки переписываются поверх main

HEAD в практических командах

// Java разработчик может встретить HEAD в таких местах:

// 1. Просмотр локальных изменений
$ git diff HEAD              // Что изменилось с последнего коммита?
$ git diff --staged HEAD     // Что в staging area?

// 2. Отмена изменений
$ git checkout -- file.java  // Откатить файл на версию из HEAD
$ git reset HEAD file.java   // Убрать файл из staging

// 3. Просмотр истории
$ git log -p HEAD~5..HEAD    // Последние 5 коммитов с деталями

// 4. Cherry-pick коммит
$ git cherry-pick abc123     // Применить конкретный коммит на HEAD

// 5. Амендирование коммита
$ git commit --amend         // Изменить последний коммит (HEAD)

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

Ошибка 1: Забыл про detached HEAD

$ git checkout abc123
$ git commit -m "Fix bug"   # Коммит создан, но не привязан к ветке!
$ git checkout main         # WARNING: you are leaving 1 commit behind
# Коммит теперь "потерян" (хотя технически, можно найти по рефлогу)

Решение: Создать ветку для этих коммитов:

$ git branch my-fix HEAD    # Создать ветку на текущий коммит
$ git checkout my-fix       # Теперь HEAD привязан к ветке

Ошибка 2: Неправильный reset

# Эти команды выглядят похоже, но делают разное!
$ git reset --soft HEAD~   # Безопасно: отмена коммита, файлы сохранены
$ git reset --hard HEAD~   # Опасно: отмена коммита И удаление файлов

Резюме

HEAD — это текущее место в Git истории. Это указатель, который указывает на коммит (обычно через текущую ветку). Понимание HEAD критично для:

  • ✅ Безопасной работы с историей
  • ✅ Правильного использования reset/revert
  • ✅ Понимания merge/rebase операций
  • ✅ Работы с detached HEAD состояниями

Просто помни: где HEAD, оттуда начинаются изменения.

Что такое HEAD в Git? | PrepBro