HEAD и ORIG_HEAD в Git

253

Что означают эти символы и что они означают?

(Я не могу найти объяснения в официальной документации)

collimarco
источник
4
Примечание: HEADсейчас (готовится к выходу git1.8.4) ' @'! Смотрите мой отредактированный ответ ниже
VonC
Примечание-бис: ' @' (для HEAD) все еще идет, но не для 1.8.4 ответ отредактирован и исправлен .
VonC
1
Примечание ter: ' @' for HEADis back для git 1.8.5 / 1.9. ответ отредактирован снова .
VonC
21
HEADи ORIG_HEADв Git похожи $PWDи $OLDPWDв Bash. :)
musiphil

Ответы:

324

HEADявляется (прямой или косвенной, то есть символической) ссылкой на текущий коммит. Это коммит, который вы проверили в рабочем каталоге (если вы не внесли какие-либо изменения или эквивалент), и это коммит, поверх которого «git commit» сделает новый. Обычно HEADэто символическая ссылка на какую-то другую именованную ветку; эта ветка в настоящее время извлечена веткой или текущей веткой. HEADтакже может указывать непосредственно на коммит; это состояние называется «отделенная голова», и его можно понимать как находящееся в неназванной анонимной ветви.

А в @одиночку это ярлык HEAD, так как Git 1.8.5

ORIG_HEADэто предыдущее состояние HEAD, заданное командами, которые могут иметь опасное поведение, чтобы их было легко восстановить. Теперь менее полезно, когда Git имеет reflog: HEAD@{1}примерно эквивалентно ORIG_HEAD( HEAD@{1}всегда является последним значением HEAD, ORIG_HEADявляется последним значением HEADперед опасной операцией).

Для получения дополнительной информации прочитайте GIT (1) страницу руководства , Руководство пользователя Git , то Git Community Book и Git Глоссарий

Якуб Наребски
источник
2
Привет Якуб. +1 за объяснение. Не могли бы вы подробно описать «примерно эквивалентную» часть HEAD @ {1}? Я ссылаюсь в своем ответе на ветку thread.gmane.org/gmane.comp.version-control.git/38379 (вы были в нем еще в феврале 2007 года), и я не совсем понял, что вы, ребята, обсуждали вокруг синтаксис @ {...}.
VonC
19
ORIG_HEAD устанавливается (я думаю) только «опасными» командами, которые перемещают HEAD более чем на один коммит. Так что ORIG_HEAD не всегда установлен, а HEAD @ {1} всегда установлен. @ {1} равен $ (git symbolic-ref HEAD) @ {1}, т. Е. Он использует reflog для текущей ветви, а не HEAD reflog.
Якуб Наребски
Riiight ... Теперь я понял :) Спасибо за это разъяснение. За то, что это стоит, я тоже проголосовал за ваш комментарий!
VonC
1
«и HEAD - это коммит, поверх которого« git commit »сделает новый.» - хорошо помнить, спасибо! Также из @VonC: «Это коммит,« git commit »строится поверх него, а« git diff --cached »и« git status »сравниваются».
Минки Пан
1
git help revisions вызывает git-scm.com/docs/gitrevisions , в котором описаны все способы ссылки на коммиты (включая HEADи ORIG_HEAD).
dahlbyk
104

Из git reset

«pull» или «merge» всегда оставляют исходный конец текущей ветви в ORIG_HEAD.

git reset --hard ORIG_HEAD

Сложный сброс приводит к тому, что ваш индексный файл и рабочее дерево возвращаются в это состояние и сбрасывает кончик ветви на этот коммит.

git reset --merge ORIG_HEAD

Изучив результат слияния, вы можете обнаружить, что изменение в другой ветке неудовлетворительное. Запуск " git reset --hard ORIG_HEAD" позволит вам вернуться туда, где вы были, но отменит локальные изменения, которые вам не нужны. " git reset --merge" сохраняет ваши локальные изменения.


Перед применением каких-либо исправлений ORIG_HEAD устанавливается на вершину текущей ветви.
Это полезно, если у вас есть проблемы с несколькими коммитами, такими как запуск ' git am' в неправильной ветке или ошибка в коммитах, которую легче исправить, изменив почтовый ящик (например, + ошибки в строках "От:").

Кроме того, слияние всегда устанавливает.git/ORIG_HEAD » в исходное состояние HEAD, поэтому проблемное слияние можно удалить с помощью « git reset ORIG_HEAD».


Примечание: отсюда

ГОЛОВА - это движущийся указатель. Иногда это означает текущую ветку, иногда нет.

Итак, ГОЛОВА не является синонимом "текущей ветки" везде.

ГОЛОВА означает «текущий» везде в git, но это не обязательно означает «текущую ветвь» (то есть отделенный HEAD).

Но это почти всегда означает «текущий коммит».
Это коммит " git commit", который строится поверх, а " git diff --cached" и " git status" сравниваются.
Это означает, что текущая ветвь только в очень ограниченных контекстах (именно тогда, когда мы хотим, чтобы имя ветви работало - сбрасывая и увеличивая наконечник ветки с помощью commit / rebase / etc.).

Reflog - это средство, позволяющее возвращаться во времени, и машины времени имеют интересное взаимодействие с понятием «ток».

HEAD@{5.minutes.ago}может означать «разыменовать HEAD symref, чтобы узнать, на какой ветке мы находимся ПРЯМО СЕЙЧАС, а затем выяснить, где была вершина этой ветви 5 минут назад».
В качестве альтернативы это может означать «что такое коммит, который я бы назвал HEAD 5 минут назад, например, если бы я делал« git show HEAD »тогда».


git1.8.4 (июль 2013) вводит введено новое обозначение!
(на самом деле, это будет для 1.8.5 или 1.9, четвертый квартал 2013 года: повторно введен с коммитом 9ba89f4 )

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

Смотрите коммит cdfd948

Ввод ' HEAD' утомителен, особенно когда мы можем использовать ' @' вместо этого.

Причина выбора « @» заключается в том, что он естественным образом следует из ref@opсинтаксиса (например HEAD@{u}), за исключением того, что у нас нет ни ref, ни операции, и когда у нас их нет, имеет смысл предположить « HEAD».

Так что теперь мы можем использовать ' git show @~1', и все это доброе совершенство.

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


Сообщение в блоге в период 1.8.4-rc3 (14, август 2013) объявила о том , что эта функция была вернулась и с задержкой (Спасибо Cupcake за головами-ап ).
Снова, это снова введено с коммитом 9ba89f4 (сентябрь 2013).

Смотрите коммит 2c2b664 :

Отменить "Добавить новый @ярлык для HEAD"

Это отменяет коммит cdfd948 , так как он не только применяется к « @» (и формам с модификаторами, как @{u}к нему), но также влияет, например, на « refs/heads/@/foo», что не должно.

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

VonC
источник
После запуска git сбросьте ORIG_HEAD и подтвердите. ORIG_HEAD все еще там в разделе Ссылки рядом с заголовком. Почему это не было удалено из поля зрения?
powder366
@ powder366 но git resetсгенерирует ORIG_HEAD. Так что вам нужно rmэто вручную. См. Например, stackoverflow.com/a/12418078/6309 .
VonC
1
@VonC @псевдоним HEADв настоящее время возвращены (временно?) Для Git 1.8.4 релиза ! Это было объявлено сегодня!
Понравился комментарий "один на один"!
Робино
2

Насколько я понимаю, HEAD указывает текущую ветвь, а ORIG_HEAD используется для хранения предыдущего HEAD перед выполнением «опасных» операций.

Например, git-rebase и git-am записывают исходный наконечник ветви перед тем, как применить какие-либо изменения.

ynimous
источник
4
HEAD не всегда указывает на текущую ветку (ее можно отключить)
VonC
1
Так что же такое «текущая ветвь», когда HEAD «отсоединен»?
cjs
@ CurtJ.Sampson Это "нет ветви". вот почему, когда вы в отстраненной голове, вы делаете это git branch foo -bдля того, чтобы «создать» ветку для этого коммита-сироты.
Рой Намир
1

От man 7 gitrevisions:

HEAD называет коммит, на котором вы основали изменения в рабочем дереве. FETCH_HEAD записывает ветку, которую вы извлекли из удаленного репозитория с вашим последним вызовом git fetch. ORIG_HEAD создается командами, которые резко перемещают ваш HEAD, чтобы записать положение HEAD перед их работой, чтобы вы могли легко изменить кончик ветви обратно в состояние до того, как вы их запустили. MERGE_HEAD записывает коммит (ы), которые вы объединяете в ветке, когда запускаете git merge. CHERRY_PICK_HEAD записывает коммит, который вы выбираете при выборе git cherry-pick.

Натан Чаппелл
источник