Reputation: 67346
You see the Git documentation saying things like
The branch must be fully merged in HEAD.
But what is Git HEAD
exactly?
Upvotes: 1369
Views: 777989
Reputation: 67
I think HEAD is best explained by checking HEAD reflog - a history of all commits HEAD was pointing too.
Here you can see each commit I was working on, with a timestamp, and comments on why HEAD changed in the form of Action + Message
It's super useful when you "lose" something due to deleting a branch or rebasing. Because 99% of the time you can still find it easily in HEAD reflog. (if you created a commit at any time)
HEAD is "commit currently synched with filesystem"
As you can see, whenever you do any action such as
HEAD will switch to a different commit (and put the previous one in the reflog so you can find it and refer to it)
Just check your reflog to see how HEAD changed
HEAD is not directly related with any branch, you can switch to any commit, and if you switch to a different branch HEAD will just get moved to the branch head commit. (note difference between HEAD and a head commit of a branch)
Normally if you work on a branch HEAD will be in synch and point to the same commit as branch
That's why this state of "detached head" is not normal and tools often complain to make sure you know what you're doing and you don't put your commits in places that are hard to find later because there is no branch pointing to it
Upvotes: -1
Reputation: 153
To understand what HEAD is, let use a practical example with two different branches, main
and feature1
from two different developers Dev1 and Dev2 working on the same project.
Case 1 with Dev1's main
branch:
name~/repo (main)
$ ls -al
total 9
drwxr-xr-x 1 AlphaLy 197121 0 Dec 22 15:09 ./
drwxr-xr-x 1 AlphaLy 197121 0 Dec 21 20:35 ../
drwxr-xr-x 1 AlphaLy 197121 0 Dec 22 15:09 .git/
-rw-r--r-- 1 AlphaLy 197121 20 Dec 21 20:35 README.md
-rw-r--r-- 1 AlphaLy 197121 0 Dec 22 15:09 test.txt
Next1
name~/repo (main)
$ cd .git/
name~/repo/.git (GIT_DIR!)
$ ls
COMMIT_EDITMSG description HEAD index logs/ ORIG_HEAD refs/
config FETCH_HEAD hooks/ info/ objects/ packed-refs
Next2
name~/repo/.git (GIT_DIR!)
$ cat HEAD
ref: refs/heads/main
We can clearly see that HEAD is a file with a line pointing to a file called main
located inside the refs/heads
directory (heads
is a directory inside the refs
directory). Refer to Next1 step to locate the refs
directory
Now lets go to the Next1 step and cd
into the refs
directory and search for the main
file inside the heads
directory and see what it contains
name~/repo/.git (GIT_DIR!)
$ cd refs
name~/repo/.git/refs (GIT_DIR!)
$ ls
heads/ remotes/ tags/
name~/repo/.git/refs/ (GIT_DIR!)
$ cd heads/
name~/repo/.git/refs/heads (GIT_DIR!)
$ ls
main maxi
name~/repo/.git/refs/heads (GIT_DIR!)
$ cat main
8b25d89f3396177416c055ab07ebf778616eecdd
8b25d89f3396177416c055ab07ebf778616eecdd
is the current commit. So, we can say that HEAD refers to a file named main
(always named after the current branch) that contains the current commit (the 40 digit character above). So HEAD refers to the current commit.
Case 2 with Dev2's feature1
branch
Here, the only difference will be in the Next2 step
name~/repo/.git (GIT_DIR!)
$ cat HEAD
ref: refs/heads/feature1
and the following:
name~/repo/.git (GIT_DIR!)
$ cat feature1
03fbf973ac1014085864234010b82393208ebbd6
03fbf973ac1014085864234010b82393208ebbd6
is the current commit on the feature1
branch. So, here again HEAD refers to a file called feature1 (named after the current branch) that contains the current commit (the 40 digit character above).
Conclusion:
HEAD is refers to the current commit not the current branch. It's just a coincidence that the file that contains that current commit is named after the current branch that we tend to say that 'HEAD refers to the current branch'.
Upvotes: 2
Reputation: 37
I haven't figured it out myself yet, but Silfheed's link to the "post-it notes slapped on a node" definition is the best I've found so far.
I would like to share my impressions of the search for a definition, otherwise why should I keep it to myself. I understand it really as stickers glued to the current position in the space of the Git tree. I miss just such a term - the current position in the GIT tree, which has its own attributes that indicate where we are.
Such concepts as "reference" or "pointer" are not clear to me. It seems to me that they imply a new level of abstraction, from the inside of which we "refer" to something. This may not be true, but this is how I see it so far.
Upvotes: 0
Reputation: 48185
Take a look at Creating and playing with branches
HEAD is actually a file whose contents determines where the HEAD variable refers:
$ cat .git/HEAD
ref: refs/heads/master
$ cat .git/refs/heads/master
35ede5c916f88d8ba5a9dd6afd69fcaf773f70ed
In this repository, the contents of the HEAD file refers to a second file named refs/heads/master. The file refs/heads/master contains the hash of the most recent commit on the master branch.
The result is HEAD points to the master branch commit from the .git/refs/heads/master file.
Upvotes: 24
Reputation: 79
HEAD is nearly literally the head of the branch. So when you are observing a branch, you are looking at the latest commit, which is this same head of the branch. However, you can point yourself to be looking at another commit further back in the history of this branch, and when you do that, you are moving the HEAD to a previous commit. As the HEAD belonged naturally to the latest commit in the branch, it is considered detached.
A visual representation. Each branch is a caterpillar, and each commit is a segment of the creature. So the HEAD will be in the segment that is most ahead. If you remove the HEAD from that to another segment to be used, you have detached the head from the natural segment. Hope it makes any sense.
Now if you detach the HEAD in the main branch, then checkout newFeature, and checkout main again, the HEAD will still be detached, and on top of another commit. I see the HEAD as a looking glass that you can point at where you want.
Upvotes: 3
Reputation: 91
There can be multiple heads in a repository. And total number of heads is always equals to total number of branches present in the repository,which means heads are nothing but latest commits of each branch
But there will be only one HEAD for a repository.HEAD is a reference which references the latest commit done at the current branch.
Its like eye of git user.Whichever commit the HEAD is referencing to, the repository starts reflecting the condition the repository had during that particular commit.
The basic nature of HEAD is to always refer the latest commit of current branch but we can move HEAD to any commit of the current branch by using git checkout "commit-hash"
Note: We can easily get commit-hash by using command git log --oneline
Upvotes: 2
Reputation: 1239
HEAD
is a pointer to the currently checked out branch or commit, it answers the question: Where am I right now in the repository? Or, in other words, it's Git's way of knowing on which commit to mirror your local Working Tree on, and whether you're currently working on a branch (attached) or not (detached).
HEAD
can be in either of two states, attached or detached, depending on if you've checked out a branch or not. Default state is attached, where any manipulation to the history is automatically recorded to the branch HEAD
is currently referencing.
In detached state experimental changes can be made without impacting any existing branch. See infographic below illustrating the difference between committing in attached vs detached state.
A common misconception is that the message You are in 'detached HEAD' state is of erroneous tone, when in fact it just describes how HEAD
is referencing the current snapshot.
Operations than can leave HEAD in detached state:
$ git checkout 14ko3
$ git checkout origin/master
$ git switch master --detached
$ git checkout v1.0.1
Moving from detached to attached state
To move from detached to attached state, you can either create a new branch from where you're at, or switch back to an existing branch.
Note: any commits created in detached state will eventually (post garbage collection) be discarded if you switch to another existing branch, without first persisting your changes in a new branch.
Figuring out which state HEAD
is currently in can be done in different ways, here are two options.
show
$ git show HEAD --oneline
14ko3 (HEAD, master) C1
# If attached, the output would have been
14ko3 (HEAD -> master) C1
status
$ git status
HEAD detached at 14ko3
If you ever want to explicitly see what HEAD
is referencing you can always inspect the .git/HEAD
file, which is the actual file Git uses internally to manage HEAD
. The file contains the name of the branch or commit hash depending on if HEAD
is detached or not.
$ cat .git/HEAD
ref: refs/heads/master
# If detached, the output would have been
14ko36e295f1a98ec57397b3acc7bc247da61ff5
Source: Above excerpt is taken from this full length post on the subject: What is HEAD in Git?
Upvotes: 24
Reputation: 12241
To quote other people:
A head is simply a reference to a commit object. Each head has a name (branch name or tag name, etc). By default, there is a head in every repository called master. A repository can contain any number of heads. At any given time, one head is selected as the “current head.” This head is aliased to HEAD, always in capitals".
Note this difference: a “head” (lowercase) refers to any one of the named heads in the repository; “HEAD” (uppercase) refers exclusively to the currently active head. This distinction is used frequently in Git documentation.
Another good source that quickly covers the inner workings of git (and therefore a better understanding of heads/HEAD) can be found here. References (ref:) or heads or branches can be considered like post-it notes stuck onto commits in the commit history. Usually they point to the tip of series of commits, but they can be moved around with git checkout
or git reset
etc.
Upvotes: 239
Reputation: 389
I am also still figuring out the internals of git, and have figured out this so far:
Let's say the current branch is master.
% cat .git/HEAD
ref: refs/heads/master
% cat .git/refs/heads/master
f342e66eb1158247a98d74152a1b91543ece31b4
% git log --oneline
f342e66 (HEAD -> master,...) latest commit
fa99692 parent of latest commit
So my thinking is the HEAD file is a convenient way to track the latest commit, instead of remembering long hash values.
Upvotes: 1
Reputation: 1744
HEAD actually is just a file for storing current branch info
and if you use HEAD in your git commands you are pointing to your current branch
you can see the data of this file by
cat .git/HEAD
Upvotes: 0
Reputation: 748
Git
is all about commits.
And Head
points to the commit which you currently checked out.
$ git cat-file -t HEAD
commit
Whenever you checkout a branch, the HEAD points to the latest commit on that branch. Contents of HEAD can checked as below (for master branch):
$ cat .git/refs/heads/master
b089141cc8a7d89d606b2f7c15bfdc48640a8e25
Upvotes: 2
Reputation: 65
A branch is actually a pointer that holds a commit ID such as 17a5. HEAD is a pointer to a branch the user is currently working on.
HEAD has a reference filw which looks like this:
ref:
You can check these files by accessing .git/HEAD
.git/refs
that are in the repository you are working in.
Upvotes: 0
Reputation: 7630
There is a, perhaps subtle, but important misconception in a number these answers. I thought I'd add my answer to clear it up.
What is
HEAD
?
HEAD
is a symbolic reference pointing to wherever you are in your commit history. It follows you wherever you go, whatever you do, like a shadow. If you make a commit, HEAD
will move. If you checkout something, HEAD
will move. Whatever you do, if you have moved somewhere new in your commit history, HEAD
has moved along with you. To address one common misconception: you cannot detach yourself from HEAD
. That is not what a detached HEAD state is. If you ever find yourself thinking: "oh no, i'm in detached HEAD state! I've lost my HEAD!" Remember, it's your HEAD. HEAD is you. You haven't detached from the HEAD, you and your HEAD have detached from something else.
HEAD
can point to a commit, yes, but typically it does not. Let me say that again. Typically HEAD
does not point to a commit. It points to a branch reference. It is attached to that branch, and when you do certain things (e.g., commit
or reset
), the attached branch will move along with HEAD
. You can see what it is pointing to by looking under the hood.
cat .git/HEAD
Normally you'll get something like this:
ref: refs/heads/master
Sometimes you'll get something like this:
a3c485d9688e3c6bc14b06ca1529f0e78edd3f86
That's what happens when HEAD
points directly to a commit. This is called a detached HEAD, because HEAD
is pointing to something other than a branch reference. If you make a commit in this state, master
, no longer being attached to HEAD
, will no longer move along with you. It does not matter where that commit is. You could be on the same commit as your master branch, but if HEAD
is pointing to the commit rather than the branch, it is detached and a new commit will not be associated with a branch reference.
You can look at this graphically if you try the following exercise. From a git repository, run this. You'll get something slightly different, but they key bits will be there. When it is time to checkout the commit directly, just use whatever abbreviated hash you get from the first output (here it is 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)
OK, so there is a small difference in the output here. Checking out the commit directly (instead of the branch) gives us a comma instead of an arrow. What do you think, are we in a detached HEAD state? HEAD is still referring to a specific revision that is associated with a branch name. We're still on the master branch, aren't we?
Now try:
git status
# HEAD detached at a3c485d
Nope. We're in 'detached HEAD' state.
You can see the same representation of (HEAD -> branch)
vs. (HEAD, branch)
with git log -1
.
HEAD
is you. It points to whatever you checked out, wherever you are. Typically that is not a commit, it is a branch. If HEAD
does point to a commit (or tag), even if it's the same commit (or tag) that a branch also points to, you (and HEAD
) have been detached from that branch. Since you don't have a branch attached to you, the branch won't follow along with you as you make new commits. HEAD
, however, will.
Upvotes: 172
Reputation: 1874
In addition to all definitions, the thing that stuck in my mind was, when you make a commit, GIT creates a commit object within the repository. Commit objects should have a parent ( or multiple parents if it is a merge commit). Now, how does git know the parent of the current commit? So HEAD is a pointer to the (reference of the) last commit which will become the parent of the current commit.
Upvotes: 2
Reputation: 8170
It feels like that HEAD
is just a tag for the last commit that you checked out.
This can be the tip of a specific branch (such as "master") or some in-between commit of a branch ("detached head")
Upvotes: 4
Reputation: 5668
HEAD is just a special pointer that points to the local branch you’re currently on.
From the Pro Git book, chapter 3.1 Git Branching - Branches in a Nutshell, in the section Creating a New Branch:
What happens if you create a new branch? Well, doing so creates a new pointer for you to move around. Let’s say you create a new branch called testing. You do this with the git branch command:
$ git branch testing
This creates a new pointer at the same commit you’re currently on
How does Git know what branch you’re currently on? It keeps a special pointer called HEAD. Note that this is a lot different than the concept of HEAD in other VCSs you may be used to, such as Subversion or CVS. In Git, this is a pointer to the local branch you’re currently on. In this case, you’re still on master. The git branch command only created a new branch — it didn’t switch to that branch.
Upvotes: 82
Reputation: 1821
I recommend this definition from github developer Scott Chacon [video reference]:
Head is your current branch. It is a symbolic reference. It is a reference to a branch. You always have HEAD, but HEAD will be pointing to one of these other pointers, to one of the branches that you're on. It is the parent of your next commit. It is what should be what was last checked-out into your working directory... This is the last known state of what your working directory was.
The whole video will give a fair introduction to the whole git system so I also recommend you to watch it all if have the time to.
Upvotes: 69
Reputation: 151214
Assuming it is not a special case called "detached HEAD", then, as stated in the O'Reilly Git book, 2nd edtion, p.69, HEAD
means:
HEAD
always refers to the most recent commit on the current branch. When you change branches,HEAD
is updated to refer to the new branch’s latest commit.
so
HEAD
is the "tip" of the current branch.
Note that we can use HEAD
to refer to the most recent commit, and use HEAD~
as the commit before the tip, and HEAD~~
or HEAD~2
as the commit even earlier, and so forth.
Upvotes: 48
Reputation: 1022
Head points to the tip of the currently checked out branch.
In your repository, there is a .git folder. Open the file in this location: .git\refs\heads. The (sha-1 hash) code in that file (master in most cases) will be the most recent commit, i.e the one seen in the output of the command git log
. More info on the .git folder: http://gitready.com/advanced/2009/03/23/whats-inside-your-git-directory.html
Upvotes: 5
Reputation: 4239
After reading all of the previous answers, I still wanted more clarity. This blog at the official git website http://git-scm.com/blog gave me what I was looking for:
The HEAD in Git is the pointer to the current branch reference, which is in turn a pointer to the last commit you made or the last commit that was checked out into your working directory. That also means it will be the parent of the next commit you do. It's generally simplest to think of it as HEAD is the snapshot of your last commit.
Upvotes: 19
Reputation: 19
Take a look at http://git-scm.com/book/en/Git-Branching-What-a-Branch-Is
Figure 3-5. HEAD file pointing to the branch you’re on.
Upvotes: 0
Reputation:
HEAD
refers to the current commit that your working copy points to, i.e. the commit you currently have checked-out. From the official Linux Kernel documentation on specifying Git revisions:
HEAD
names the commit on which you based the changes in the working tree.
Note, however, that in the upcoming version 1.8.4 of Git, @
can also be used as a shorthand for HEAD
, as noted by Git contributor Junio C Hamano in his Git Blame blog:
Instead of typing "HEAD", you can say "@" instead, e.g. "git log @".
Stack Overflow user VonC also found some interesting information on why @
was chosen as a shorthand in his answer to another question.
Also of interest, in some environments it's not necessary to capitalize HEAD
, specifically in operating systems that use case-insensitive file systems, specifically Windows and OS X.
Upvotes: 29
Reputation: 6193
These two may confusing you:
head
Pointing to named references a branch recently submitted. Unless you use the package reference , heads typically stored in $ GIT_DIR/refs/heads/.
HEAD
Current branch, or your working tree is usually generated from the tree HEAD is pointing to. HEAD must point to a head, except you are using a detached HEAD.
Upvotes: 0
Reputation: 1175
I'd just like to detail a few things in Greg Hewgil's accepted answer. According to the Git Pocket Guide
Branch:
the branch itself is defined as all points reachable in the commit graph from the named commit (the “tip” of the branch).
HEAD: A special type of Ref
The special ref HEAD determines what branch you are on...
Refs
Git defines two kinds of references, or named pointers, which it calls “refs”:
- A simple ref, which points directly to an object ID (usually a commit or tag)
- A symbolic ref (or symref), which points to another ref (either simple or symbolic)
As Greg mentioned, HEAD can be in a "detached state". So HEAD can be either a simple ref (for a detached HEAD) or a symref.
if HEAD is a symbolic ref for an existing branch, then you are “on” that branch. If, on the other hand, HEAD is a simple ref directly naming a commit by its SHA-1 ID, then you are not “on” any branch, but rather in “detached HEAD” mode, which happens when you check out some earlier commit to examine.
Upvotes: 15
Reputation: 79
I think 'HEAD' is current check out commit. In other words 'HEAD' points to the commit that is currently checked out.
If you have just cloned and not checked out I don't know what it points to, probably some invalid location.
Upvotes: 7
Reputation: 11728
A great way to drive home the point made in the correct answers is to run
git reflog HEAD
, you get a history of all of the places HEAD has pointed.
Upvotes: 6
Reputation: 3198
As a concept, the head is the latest revision in a branch. If you have more than one head per named branch you probably created it when doing local commits without merging, effectively creating an unnamed branch.
To have a "clean" repository, you should have one head per named branch and always merge to a named branch after you worked locally.
This is also true for Mercurial.
Upvotes: -5
Reputation: 994589
You can think of the HEAD as the "current branch". When you switch branches with git checkout
, the HEAD revision changes to point to the tip of the new branch.
You can see what HEAD points to by doing:
cat .git/HEAD
In my case, the output is:
$ cat .git/HEAD
ref: refs/heads/master
It is possible for HEAD to refer to a specific revision that is not associated with a branch name. This situation is called a detached HEAD.
Upvotes: 991