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


1027

Вы видите документацию Git, в которой говорится

Ветка должна быть полностью объединена в HEAD.

Но что такое Git HEAD?



Ответы:


775

Вы можете думать о ГОЛОВЕ как о "текущей ветви". Когда вы переключаете ветки с помощью git checkout, ревизия HEAD изменяется, чтобы указывать на вершину новой ветки.

Вы можете увидеть, на что указывает HEAD:

cat .git/HEAD

В моем случае вывод:

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

HEAD может ссылаться на конкретную ревизию, которая не связана с именем ветви. Эта ситуация называется отдельной головой .


53
Итак, git HEAD зависит от контекста, в каком филиале вы находитесь, правильно? Еще дальше, вы как разработчик? Думаю, я спрашиваю, будет ли Git HEAD глобальной вещью репозитория или индивидуальной для каждого разработчика?
Бобобобо

91
@bobobobo: Правильно, HEAD похож на указатель на текущую ветку. Когда вы извлекаете другую ветку, HEAD изменяется, чтобы указать на новую. Текущий заголовок является локальным для каждого репозитория и поэтому индивидуален для каждого разработчика.
Грег Хьюгилл

16
@Meng Это один помог мне, надеюсь , что это помогает: marklodato.github.com/visual-git-guide/index-en.html
Raphael

54
@ 動靜 能量: HEAD может указывать на любой коммит, он не обязательно должен быть последним коммитом в любой ветке. (Когда HEAD указывает на коммит, который не является последним коммитом в ветви, это «отдельный HEAD»).
Грег Хьюгилл

127
HEAD не является "текущей веткой". Is - это имя, присвоенное коммиту, с которого было инициализировано текущее состояние рабочего дерева. В более практических терминах его можно рассматривать как символическую ссылку на извлеченный коммит.
Бен Коллинз

184

Цитировать других людей :

Голова - это просто ссылка на объект фиксации. У каждой головы есть имя (название ветви или имя тега и т. Д.) По умолчанию в каждом репозитории есть заголовок с именем master. Хранилище может содержать любое количество головок. В любой момент времени одна голова выбрана в качестве «текущей головы». Эта голова имеет псевдоним HEAD, всегда в столицах ".

Обратите внимание на это различие: «голова» (в нижнем регистре) относится к любой из названных голов в хранилище; «ГОЛОВА» (верхний регистр) относится исключительно к текущей активной голове. Это различие часто используется в документации Git.

Другой хороший источник, который быстро охватывает внутреннюю работу git (и, следовательно, для лучшего понимания head / HEAD), можно найти здесь . Ссылки (ref :) или заголовки или ветки могут рассматриваться как заметки, прикрепленные к коммитам в истории коммитов. Обычно они указывают на конец серии коммитов, но их можно перемещать с помощью git checkoutили git resetт. Д.


Из этого: «У каждой головы есть имя». И «одна голова выбрана в качестве« текущей головы ». Эта голова имеет псевдоним "HEAD". Итак, из этого я заключаю, что «ГОЛОВА» не относится к ситуации «отсоединенного ГОЛОВА».
gxyd

1
@gxyd, если это тот случай, когда HEAD не указывает на «голову», это отдельная ГОЛОВА. Он указывает на идентификатор фиксации указанного вами коммита (используя, например git checkout HEAD~2), который не является идентификатором фиксации известного заголовка. См. Статью на eagain.net/articles/git-for-computer-scientists для более подробного объяснения.
Silfheed

1
@Silfheed: Вообще, я думаю, что этот ответ концептуально более обоснован, чем принятый (хотя использование строчной «головы» для ссылки на ветку сбивает с толку многих людей). Однако git revertэто не хороший пример перемещения ветки, чтобы не быть на кончике, потому что git revertпросто создает некоторые новые коммиты и все еще оставляет текущую ветвь на (новом) кончике.
LarsH

1
«который не является идентификатором фиксации известного заголовка» - фактически, отсоединенный заголовок может указывать на идентификатор фиксации, который также является идентификатором фиксации известного заголовка (или нескольких заголовков). Что делает его отсоединенным, так это то, что HEAD указывает непосредственно на идентификатор фиксации, а не на голову. Это повлияет на поведение будущих commitс, resetс и т. Д.
LarsH

1
@LarsH: Хорошая точка на отдельном заголовке, указывающая на идентификатор фиксации вместо ссылки. Вы можете убедиться в этом, посмотрев на .git / HEAD. Если он отсоединен, он будет содержать хеш коммита, даже если это тот же коммит, что и у известного заголовка. Если он прикреплен, он будет содержать путь к голове (то есть 'ref: refs / head / bob'). Что касается команды возврата, после 8 лет я никогда не поймал эту опечатку. Git reset - это то, что позволяет вам настроить конкретную голову так, чтобы она указывала на конкретный коммит.
Silfheed

62

Я рекомендую это определение от разработчика github Скотта Чакона [ ссылка на видео ]:

Голова - это ваша текущая ветвь. Это символическая ссылка. Это ссылка на ветку. У вас всегда есть HEAD, но HEAD будет указывать на один из этих других указателей, на одну из ветвей, на которой вы находитесь. Это родитель вашего следующего коммита. Это то, что должно быть последним извлеченным в вашем рабочем каталоге ... Это последнее известное состояние вашего рабочего каталога.

Все видео даст хорошее представление о всей системе git, поэтому я также рекомендую вам посмотреть все, если есть время.


34
Таким образом, истинное определение - «родитель вашего следующего коммита»
Николас

1
а также "вещь, указывающая на следующую ветку, которая будет двигаться"
Николас

@nicolas - Я не думаю, что это правда. HEAD может указывать на любой коммит, он не обязательно должен указывать на ветку - когда это не так, вы находитесь в режиме «отсоединенного HEAD».
подводное

23
Видео отличное, но, к сожалению, оно плохо подходит для Stack Overflow. Что если видео будет снято в будущем? Тогда ваша ссылка ни к чему не приведет. Лучший ответ будет включать стенограмму того, что Скотт говорит в видео.

2
Скотт говорит, что HEAD - это указатель на ветку. Но HEAD также может указывать на старые коммиты. Это очень странно.
Fixee

60

HEAD - это просто специальный указатель, который указывает на локальную ветку, в которой вы находитесь.

Из книги Pro Git , глава 3.1 Ветвление Git - ветви в двух словах , в разделе Создание новой ветки :

Что произойдет, если вы создадите новую ветку? Ну, это создает новый указатель для вас, чтобы двигаться. Допустим, вы создаете новую ветку под названием «Тестирование». Вы делаете это с помощью команды git branch:

$ git branch testing 

Это создаст новый указатель на тот же коммит, на котором вы сейчас находитесь

введите описание изображения здесь

Как Git узнает, в какой ветке вы сейчас находитесь? Он содержит специальный указатель под названием HEAD. Обратите внимание, что это сильно отличается от концепции HEAD в других VCS, к которым вы можете привыкнуть, таких как Subversion или CVS. В Git это указатель на локальную ветку, в которой вы находитесь. В этом случае вы все еще на мастере. Команда git branch только создала новую ветку - она ​​не переключалась на эту ветку.

введите описание изображения здесь


4
Хорошо, я мог бы использовать изображение, показывающее отдельный чехол HEAD, хотя
Дон Хэтч

@DonHatch, хорошее объяснение отдельного HEAD stackoverflow.com/a/35301963/1074179
Александр

3
Хороший ответ. Ветви - это не что иное, как помеченные коммиты. Когда вы делаете новые коммиты, эта метка перемещается в новый новый коммит. Когда вы извлекаете коммит, у которого нет метки, он находится в отдельном состоянии HEAD. Это означает, что HEAD указывает на коммит, который не имеет метки ветвления. Если вы извлекаете 34ac2из вышеприведенного примера, теперь HEAD будет указывать на этот коммит, и он называется отделенным HEAD. В этом состоянии вы также можете вносить изменения, экспериментировать и фиксировать изменения, но как только вы извлечете другую ветку, вы потеряете все свои изменения, если, конечно, вы не создадите новую ветку.
sleepwalkerfx

1
@sleepwalkerfx, но вы можете извлечь коммит, который имеет метку ветви и все еще находиться в состоянии отдельного заголовка, потому что ваш HEAD больше не указывает на метку ветки, а на идентификатор фиксации ветви
Marc

1
@sleepwalkerfx Я думаю, что сейчас мы говорим о семантике. Вы правы, метка ветки - это текстовая ссылка на конкретный коммит. Это, однако, не коммит. Так что если вы сделали a git logи получили что-то подобное commit ad0265... HEAD -> foo ..., это означало бы, что fooветвь является ссылкой для фиксации id ad0265. Оформление проверки текстовой ссылки fooне является отдельной головой. Извлечение идентификатора коммита ad0265приведет к отстраненной голове. Может быть, мне не хватает тонкости в том, что вы говорите. Я надеюсь, что эта стена текста поможет обнаружить, где я потерялся.
Марк

40

Если предположить, что это не особый случай, называемый «отделенная ГОЛОВА», то, как указано в книге О'Рейли Гит, 2-е издание, стр.69, HEADозначает:

HEADвсегда ссылается на самый последний коммит в текущей ветке. Когда вы меняете ветки, HEADобновляется, чтобы ссылаться на последний коммит новой ветки.

так

HEADявляется «наконечником» текущей ветви .

Обратите внимание, что мы можем использовать HEADссылку на самый последний коммит и использовать HEAD~в качестве коммита до подсказки, и / HEAD~~или HEAD~2в качестве коммита еще раньше, и так далее.


27

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

Что такое HEAD?

ГОЛОВА ТЫ

HEADсимволическая ссылка, указывающая на то, где вы находитесь в истории коммитов. Он следует за вами, куда бы вы ни пошли, что бы вы ни делали, как тень. Если вы сделаете коммит, HEADпереедете. Если вы что-то оформите, HEADпереедете. Что бы вы ни делали, если вы переехали куда-то новое в историю ваших коммитов, HEADвы перешли вместе с вами. Чтобы устранить одно распространенное заблуждение: вы не можете оторваться отHEAD . Это не то, что состояние отделенного HEAD. Если вы когда-нибудь обнаружите, что думаете: «О, нет, я нахожусь в отдельном состоянии ГОЛОВА! Я потерял свою ГОЛОВУ!» Помните, это ваша голова. ГОЛОВА это ты. Вы не отсоединились от ГОЛОВОЙ, вы и ваша ГОЛОВА отошли от чего-то другого.

К чему может присоединиться ГОЛОВА?

HEADможет указывать на коммит, да, но обычно это не так. Позвольте мне сказать это снова. Обычно HEADне указывает на коммит. Это указывает на ссылку ветви. Он прикреплен к этой ветви, и когда вы делаете определенные вещи (например, commitили reset), присоединенная ветвь будет двигаться вместе с HEAD. Вы можете увидеть, на что он указывает, заглянув под капот.

cat .git/HEAD

Обычно вы получите что-то вроде этого:

ref: refs/heads/master

Иногда вы получите что-то вроде этого:

a3c485d9688e3c6bc14b06ca1529f0e78edd3f86

Вот что происходит, когда HEADуказывает непосредственно на коммит. Это называется отделенным HEAD, потому что HEADуказывает на что-то, кроме ссылки на ветку. Если вы делаете коммит в этом состоянии, masterбольше не привязаны к нему HEAD, больше не будут двигаться вместе с вами. Неважно, где находится этот коммит. Вы можете использовать тот же коммит, что и ваша основная ветка, но если HEADон указывает на коммит, а не на ветку, он отсоединяется, и новый коммит не будет связан со ссылкой на ветку.

Вы можете посмотреть на это графически, если попытаетесь выполнить следующее упражнение. Запустите это из репозитория git. Вы получите что-то немного другое, но они будут иметь ключевое значение. Когда пришло время напрямую извлекать коммит, просто используйте любой сокращенный хеш, который вы получите из первого вывода (здесь он есть a3c485d).

git checkout master
git log --pretty=format:"%h:  %d" -1
# a3c485d:   (HEAD -> master)

git checkout a3c485d -q # (-q is for dramatic effect)
git log --pretty=format:"%h:  %d" -1   
# a3c485d:   (HEAD, master)

Итак, здесь небольшая разница в выводе. Проверка коммита напрямую (вместо ветки) дает нам запятую вместо стрелки. Как вы думаете, мы находимся в отдельном состоянии головы? HEAD все еще ссылается на конкретную ревизию, связанную с именем ветви. Мы все еще на главной ветке, не так ли?

Теперь попробуйте:

git status
# HEAD detached at a3c485d

Нет. Мы находимся в состоянии «отсоединенная ГОЛОВА».

Вы можете увидеть то же представление (HEAD -> branch)против (HEAD, branch)с git log -1.

В заключении

HEADэто ты. Это указывает на то, что вы проверили, где бы вы ни находились. Как правило, это не коммит, это ветка. Если HEAD он указывает на коммит (или тег), даже если это тот же коммит (или тег), на который указывает ветка, вы (и HEAD) были отсоединены от этой ветви. Поскольку к вам не прикреплена ветка, ветка не будет следовать за вами, когда вы делаете новые коммиты. HEADВпрочем, будет.


1
Мне нравится этот ответ, потому что, хотя документация описывает правду, программное обеспечение определяет правду. .git/HEADэто то, что программное обеспечение считает головой.
Дон Брэнсон

2
Только для его концептуального определения это должен быть принятый ответ.
ата

22

HEADотносится к текущему коммиту, на который указывает ваша рабочая копия, т.е. к коммиту, который вы в данный момент извлекли. Из официальной документации Linux Kernel по указанию ревизий Git :

HEAD называет коммит, на котором вы основали изменения в рабочем дереве.

Тем не менее, обратите внимание, что в следующей версии Git 1.8.4 @также можно использовать для краткости HEAD, как отметил участник Git Джунио С. Хамано в своем блоге Git Blame :

Вместо того, чтобы вводить «HEAD», вы можете сказать «@», например, «git log @».

Пользователь Stack Overflow VonC также нашел интересную информацию о том, почему он @был выбран в качестве краткого описания в своем ответе на другой вопрос .

Также интересно, что в некоторых средах нет необходимости использовать заглавные буквы HEAD , особенно в операционных системах, использующих файловые системы без учета регистра, особенно в Windows и OS X.


17

Посмотрите на Создание и игра с ветками

HEAD - это файл, содержимое которого определяет, куда ссылается переменная HEAD:

$ cat .git/HEAD
ref: refs/heads/master
$ cat .git/refs/heads/master
35ede5c916f88d8ba5a9dd6afd69fcaf773f70ed

В этом хранилище содержимое файла HEAD ссылается на второй файл с именем refs /head / master . Файл refs /глав / мастер содержит хэш самого последнего коммита в ветке master.

В результате HEAD указывает на коммит главной ветки из файла .git / refs /head / master .

введите описание изображения здесь


1
Осторожно: ссылка на gitguys.com указывает на припаркованный домен.
MKesper

14

Я просто хотел бы подробно рассказать о нескольких вещах в принятом ответе Грега Хьюджила. Согласно Git Pocket Guide

Филиал:

Сама ветвь определяется как все точки, достижимые в графе коммитов из именованного коммита («кончик» ветки).

ГОЛОВА: особый тип Реф

Специальный ref HEAD определяет, на какой ветке вы находитесь ...

Refs

Git определяет два вида ссылок или именованных указателей, которые он называет «refs»:

  • Простой реф, который указывает непосредственно на идентификатор объекта (обычно коммит или тэг)
  • Символический ref (или symref), который указывает на другой ref (простой или символический)

Как упомянул Грег, HEAD может находиться в «обособленном состоянии». Таким образом, HEAD может быть либо простым ref (для отдельного HEAD), либо symref.

если HEAD является символической ссылкой на существующую ветвь, то вы находитесь «на» этой ветке. Если, с другой стороны, HEAD - это простой реф, непосредственно именующий коммит его идентификатором SHA-1, то вы находитесь не в «любой» ветви, а в режиме «отсоединенного HEAD», который происходит, когда вы проверяете некоторые ранее. поручить изучить.


Спасибо, @mike! Это первый ответ, который проясняет, что происходит, когда вы проверяете предыдущий коммит. Просматривая книгу на сайте git, у меня сложилось впечатление, что «оторванная ГОЛОВА» - это патологическое состояние, в которое вы попадаете, только если совершаете какие-то странные оскорбления. Но проверка более раннего коммита не является странной вещью, и когда вы делаете это, HEAD не является «вершиной текущей ветви». Так что я впервые чувствую, что действительно понимаю.
Нат Кун

7

Я думаю, что «HEAD» - это текущий коммит. Другими словами, «HEAD» указывает на коммит, который в данный момент извлечен.

Если вы только что клонировали и не проверили, я не знаю, на что это указывает, возможно, какое-то неверное местоположение.


Да, специальная ссылка HEAD- это любой коммит, который вы в данный момент получили. Подробности см. В руководстве (соответствующий пункт следует сразу за Рис. 3.4).
Calrion

1
Если вы клонируете репозиторий, git по умолчанию проверит masterветку - поэтому HEAD будет указывать на master.
слеске

1
@sleske, если вы клонируете репозиторий без специальных опций, git проверит удаленную главу. это обычно master, но это не всегда. Смотритеremote set-head
De Novo

Мой предыдущий комментарий был верным, за исключением ссылки на remote set-head, которая влияет только на локальную ветку по умолчанию и не меняет настройки по умолчанию на сервере.
De Novo

5

Голова указывает на верхушку проверенной ветки.

введите описание изображения здесь

В вашем репозитории есть папка .git. Откройте файл в этом месте: .git \ refs \head. Код (sha-1 hash) в этом файле (в большинстве случаев master) будет самым последним коммитом, то есть тем, который виден в выходных данных команды git log. Дополнительная информация о папке .git: http://gitready.com/advanced/2009/03/23/whats-inside-your-git-directory.html.


1
Это распространенное заблуждение, что кончик текущей ветви указывает на самый последний коммит. Обычно это так, но это также не редкость git reset HEAD^, и тогда самый последний коммит (предыдущий совет) больше не указывается кончиком ветви.
LarsH

4

Отличный способ git reflog HEADдонести до ума то , что было сделано в правильных ответах, - это бежать , вы получаете историю всех мест, которые указал HEAD.


4

Прочитав все предыдущие ответы, я все еще хотел большей ясности. Этот блог на официальном сайте Git http://git-scm.com/blog дал мне то, что я искал:

HEAD: указатель на последний моментальный снимок, следующий родитель

HEAD в Git - это указатель на текущую ссылку на ветвь, которая, в свою очередь, является указателем на последний сделанный вами коммит или последний коммит, который был извлечен в ваш рабочий каталог. Это также означает, что это будет родитель следующего коммита, который вы делаете. Как правило, проще всего думать об этом, поскольку HEAD - это снимок вашего последнего коммита.


1
HEAD: последний моментальный снимок, следующий родитель не точен. HEADэто не коммит; это указывает на один.
jub0bs

Нет необходимости в сарказме; перед редактированием, хотя цитата была точной, большие жирные буквы были упрощением и немного вводили в заблуждение. Теперь лучше.
jub0bs

1
Если вы прочитали следующую строку: HEAD в Git - это указатель на текущую ссылку на ветвь, которая, в свою очередь, является указателем на последний сделанный вами коммит или последний коммит, который был извлечен в ваш рабочий каталог. - Обратите внимание на использование слова «указатель» там.
user3751385

Хотя описание «последнего моментального снимка» дает концептуальное представление о том, как обычно предполагается использовать HEAD, на самом деле оно не совсем точное. Если я сделаю коммит, а затем переключусь на другую ветку, HEAD больше не будет указывать на последний снимок коммита. Он указывает на последний моментальный снимок коммита в ветке, на которую я только что переключился. Если я checkout HEAD^, то теперь HEAD даже не указывает на последний моментальный снимок коммита в любой ветви.
LarsH

«Родитель вашего следующего коммита (если вы должны были сделать коммит прямо сейчас)» более точен, но в git есть много других операций, кроме комита, на которые влияет HEAD. Действительно, в конце концов, голова HEAD, и его природа определяется как она влияет на такие команды , как commit, merge, rebase, logи т.д. Но концептуально может быть «(указатель) текущее положение» представляет собой резюме хорошо.
LarsH

3

Такое ощущение, что HEADэто всего лишь тег для последнего зафиксированного вами коммита.

Это может быть кончик определенной ветви (например, «master») или некоторый промежуточный коммит ветви («detached head»)


1

В дополнение ко всем определениям у меня в голове застряло то, что когда вы делаете коммит, GIT создает объект фиксации в репозитории. У объектов коммитов должен быть родитель (или несколько родителей, если это коммит слияния). Теперь, как git узнает родителя текущего коммита? Таким образом, HEAD является указателем на (ссылку на) последний коммит, который станет родителем текущего коммита.


0

Эти двое могут сбить вас с толку:

глава

Указывая на именованные ссылки ветка недавно представленная. Если вы не используете ссылку на пакет, заголовки обычно хранятся в $ GIT_DIR / refs /head /.

ГЛАВА

Текущая ветвь или ваше рабочее дерево обычно генерируется из дерева, на которое указывает HEAD. ГОЛОВА должна указывать на голову, за исключением того, что вы используете отдельную ГОЛОВУ.


0

Взгляните на http://git-scm.com/book/en/Git-Branching-What-a-Branch-Is

Рисунок 3-5. Файл HEAD, указывающий на ветку, в которой вы находитесь.


4
Ответы, содержащие только ссылки, обычно не одобряются в Stackoverflow, пожалуйста, укажите соответствующую информацию в своем ответе.
HaskellElephant

2
Это не совсем правильно. То, что HEADотносится к этому, зависит от того, говорите ли вы о «голом» или «не голом» репо. В контексте репозитория non-bare, он фактически ссылается на текущий извлеченный коммит, который не требует, чтобы к нему была присоединена ветвь (т. Е. В отключенном HEADсостоянии).

0

Ветвь фактически является указателем , который держит совершить ID , такие как 17a5 . HEAD - указатель на ветку, над которой в данный момент работает пользователь.

ГЛАВА есть ссылка на ссылку, которая выглядит следующим образом:

ссылка:

Вы можете проверить эти файлы, зайдя .git/HEAD .git/refsв репозиторий, в котором вы работаете.


0

Gitэто все о коммитах.
И Headуказывает на коммит, который вы в настоящее время извлекли.

$ git cat-file -t HEAD
commit

Всякий раз, когда вы извлекаете ветку, HEAD указывает на последний коммит в этой ветке. Содержимое HEAD можно проверить, как показано ниже (для основной ветки):

$ cat .git/refs/heads/master
  b089141cc8a7d89d606b2f7c15bfdc48640a8e25

-5

Как концепция, глава является последней ревизией в отрасли. Если у вас есть более одного заголовка на именованную ветвь, вы, вероятно, создали его при выполнении локальных коммитов без слияния, фактически создавая неназванную ветвь.

Чтобы иметь «чистый» репозиторий, у вас должна быть одна голова на именованную ветвь и всегда сливаться с именованной ветвью после локальной работы.

Это также верно для Mercurial .


4
Это верно для Mercurial, но не для Git.
Восстановить Монику - Нотмейнард
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.