HEAD and ORIG_HEAD in Git
Asked Answered
G

4

298

What do these symbols refer to and what do they mean?

(I can't find any explanation in official documentation)

Guadalupeguadeloupe answered 8/6, 2009 at 13:17 Comment(5)
Note: HEAD is now (upcoming git1.8.4) '@'! See my edited answer belowRedfish
Note-bis: '@' (for HEAD) is still coming, but not for 1.8.4 answer edited and amended.Redfish
Note ter: '@' for HEAD is back for git 1.8.5/1.9. answer edited again.Redfish
HEAD and ORIG_HEAD in Git are like $PWD and $OLDPWD in Bash. :)Choric
I find that HEAD is not identical to @ when running git checkout. In addition, I also find that HEAD is not identical to HEAD~0 when running git checkout. In fact, @ is identical to HEAD~0. The following screenshots are as follows: @ vs HEAD and HEAD vs HEAD~0Breadboard
K
372

HEAD is (direct or indirect, i.e. symbolic) reference to the current commit. It is a commit that you have checked in the working directory (unless you made some changes, or equivalent), and it is a commit on top of which "git commit" would make a new one. Usually HEAD is symbolic reference to some other named branch; this branch is currently checked out branch, or current branch. HEAD can also point directly to a commit; this state is called "detached HEAD", and can be understood as being on unnamed, anonymous branch.

And @ alone is a shortcut for HEAD, since Git 1.8.5

ORIG_HEAD is previous state of HEAD, set by commands that have possibly dangerous behavior, to be easy to revert them. It is less useful now that Git has reflog: HEAD@{1} is roughly equivalent to ORIG_HEAD (HEAD@{1} is always last value of HEAD, ORIG_HEAD is last value of HEAD before dangerous operation).

For more information read git(1) manpage / [gitrevisions(7) manpage][git-revisions], Git User's Manual, the Git Community Book and Git Glossary

Kronick answered 9/6, 2009 at 0:5 Comment(9)
Hi Jakub. +1 for the explanation. Could you detail the "roughly equivalent" part of HEAD@{1} ? I refer in my answer to the thread thread.gmane.org/gmane.comp.version-control.git/38379 (you were in it, back in February 2007), and I did not exactly understood the discussion you guys were having around the @{...} syntax.Redfish
ORIG_HEAD is set (I think) only by 'dangerous' commands, that move HEAD more than one commit. So ORIG_HEAD is not always set, while HEAD@{1} is always set. @{1} is $(git symbolic-ref HEAD)@{1}, i.e. it is uses reflog for current branch, not HEAD reflog.Faliscan
@RJFalconer: I don't know if Git dicumentation that was on kernel.org would go back - access is now much more strict. Try links from Git Homepage (Documentation section).Faliscan
"and HEAD is a commit on top of which "git commit" would make a new one. " -- good to remember, thanks! Also from @VonC, 'It is the commit "git commit" builds on top of, and "git diff --cached" and "git status" compare against.'Prayerful
git help revisions brings up git-scm.com/docs/gitrevisions, which describes all the ways to reference commits (including HEAD and ORIG_HEAD).Stellular
git show ORIG_HEAD is a good sanity check before using that revision in a commandSettee
In some cases, HEAD is not identical to @. Here are a bunch of screenshots.Breadboard
@Breadboard - it looks like in this case there is a tag named @, which probably shouldn't be allowed. git-scm.com/docs/gitrevisions says explicitly "@ alone is a shortcut for HEAD"Faliscan
I always assumed that this was the HEAD of the last fetch from the origin remote… :)Calais
R
128

ORIG_HEAD

From git reset

"pull" or "merge" always leaves the original tip of the current branch in ORIG_HEAD.

git reset --hard ORIG_HEAD

Resetting hard to it brings your index file and the working tree back to that state, and resets the tip of the branch to that commit.

git reset --merge ORIG_HEAD

After inspecting the result of the merge, you may find that the change in the other branch is unsatisfactory. Running "git reset --hard ORIG_HEAD" will let you go back to where you were, but it will discard your local changes, which you do not want. "git reset --merge" keeps your local changes.


Before any patches are applied, ORIG_HEAD is set to the tip of the current branch.
This is useful if you have problems with multiple commits, like running 'git am' on the wrong branch or an error in the commits that is more easily fixed by changing the mailbox (e.g. +errors in the "From:" lines).

In addition, merge always sets '.git/ORIG_HEAD' to the original state of HEAD so a problematic merge can be removed by using 'git reset ORIG_HEAD'.


Git 2.40 (Q1 2023) documents ORIG_HEAD a bit more:

See commit f1c9243, commit c6eec9c, commit 0c514d5, commit d03c773, commit e29678b (10 Jan 2023) by Philippe Blain (phil-blain).
(Merged by Junio C Hamano -- gitster -- in commit 9c2003a, 21 Jan 2023)

git-rebase.txt: add a note about 'ORIG_HEAD' being overwritten

Reported-by: Erik Cervin Edin
Signed-off-by: Philippe Blain
Acked-by: Phillip Wood

'ORIG_HEAD' is written at the start of the rebase, but is not guaranteed to still point to the original branch tip at the end of the rebase.

Indeed, using other commands that write 'ORIG_HEAD' during the rebase, like splitting a commit using 'git reset'(man) HEAD^', will lead to 'ORIG_HEAD' being overwritten.
This causes confusion for some users.

Add a note about that in the 'Description' section, and mention the more robust alternative of using the branch's reflog.

git rebase now includes in its man page:

[NOTE]:
ORIG_HEAD is not guaranteed to still point to the previous branch tip at the end of the rebase if other commands that write that pseudo-ref (e.g. git reset) are used during the rebase.
The previous branch tip, however, is accessible using the reflog of the current branch (i.e. @{1}).

And:

revisions.txt: be explicit about commands writing 'ORIG_HEAD'

Signed-off-by: Philippe Blain
Acked-by: Phillip Wood

When mentioning 'ORIG_HEAD', be explicit about which command write that pseudo-ref, namely 'git am'(man), 'git merge'(man), 'git rebase'(man) and 'git reset'(man).

revisions now includes in its man page:

ORIG_HEAD is created by commands that move your HEAD in a drastic way (git am, git merge, git rebase, git reset), to record the position of the HEAD before their operation, so that you can easily change the tip of the branch back to the state before you ran them.


HEAD

Note: from here

HEAD is a moving pointer. Sometimes it means the current branch, sometimes it doesn't.

So HEAD is NOT a synonym for "current branch" everywhere already.

HEAD means "current" everywhere in git, but it does not necessarily mean "current branch" (i.e. detached HEAD).

But it almost always means the "current commit".
It is the commit "git commit" builds on top of, and "git diff --cached" and "git status" compare against.
It means the current branch only in very limited contexts (exactly when we want a branch name to operate on --- resetting and growing the branch tip via commit/rebase/etc.).

Reflog is a vehicle to go back in time and time machines have interesting interaction with the notion of "current".

HEAD@{5.minutes.ago} could mean "dereference HEAD symref to find out what branch we are on RIGHT NOW, and then find out where the tip of that branch was 5 minutes ago".
Alternatively it could mean "what is the commit I would have referred to as HEAD 5 minutes ago, e.g. if I did "git show HEAD" back then".


git1.8.4 (July 2013) introduces introduced a new notation!
(Actually, it will be for 1.8.5, Q4 2013: reintroduced with commit 9ba89f4), by Felipe Contreras.

Instead of typing four capital letters "HEAD", you can say "@" now,
e.g. "git log @".

See commit cdfd948

Typing 'HEAD' is tedious, especially when we can use '@' instead.

The reason for choosing '@' is that it follows naturally from the ref@op syntax (e.g. HEAD@{u}), except we have no ref, and no operation, and when we don't have those, it makes sens to assume 'HEAD'.

So now we can use 'git show @~1', and all that goody goodness.

Until now '@' was a valid name, but it conflicts with this idea, so let's make it invalid. Probably very few people, if any, used this name.

Redfish answered 8/6, 2009 at 13:27 Comment(6)
After running git reset ORIG_HEAD and commit. ORIG_HEAD is still there under References next to HEAD. Why was it not removed from the view?Criticize
@Criticize but a git reset will generate a ORIG_HEAD. So you need to rm it manually. See https://mcmap.net/q/11622/-how-to-delete-an-orig_head-branch-in-git for instance.Redfish
@Redfish the @ alias for HEAD is being reverted (temporarily?) for the Git 1.8.4 release! It was just announced today!Ettie
Enjoyed the "heads-up" comment!Copyholder
@snakecharmerb Yes, as this answer above states, @ alone is a shortcut for HEAD dates from Git 1.8.5 and commit 9ba89f4, Q3 2013.Redfish
@snakecharmerb Good point. I have removed the revert part, to keep only the announcement.Redfish
G
5

From man 7 gitrevisions:

HEAD names the commit on which you based the changes in the working tree. FETCH_HEAD records the branch which you fetched from a remote repository with your last git fetch invocation. ORIG_HEAD is created by commands that move your HEAD in a drastic way, to record the position of the HEAD before their operation, so that you can easily change the tip of the branch back to the state before you ran them. MERGE_HEAD records the commit(s) which you are merging into your branch when you run git merge. CHERRY_PICK_HEAD records the commit which you are cherry-picking when you run git cherry-pick.

Gypsum answered 28/2, 2020 at 9:32 Comment(0)
M
2

My understanding is that HEAD points the current branch, while ORIG_HEAD is used to store the previous HEAD before doing "dangerous" operations.

For example git-rebase and git-am record the original tip of branch before they apply any changes.

Mortise answered 8/6, 2009 at 13:35 Comment(3)
HEAD does not always point on the current branch (it can be detached)Redfish
So what is the "current branch" when HEAD is "detached?"Ballot
@CurtJ.Sampson That is "no branch". that's why when you in detached head , you do git branch foo -b in order to "create" a branch for that orphans commits.Gallows

© 2022 - 2024 — McMap. All rights reserved.