views:

72

answers:

3

Hello,

Can someone tell me difference between HEAD / Working Tree / Index in Git?

From what I understand, they are all names for different branches. Is my assumption correct?

EDIT: I found this "A single git repository can track an arbitrary number of branches, but your working tree is associated with just one of them (the "current" or "checked out" branch), and HEAD points to that branch." Does this mean that HEAD and working tree are always the same?

+2  A: 

Your working tree is what is actually in the files that you are currently working on. HEAD is a pointer to the branch or commit that you last checked out, and which will be the parent of a new commit if you make it. For instance, if you're on the master branch, then HEAD will point to master, and when you commit, that new commit will be a descendent of the revision that master pointed to, and master will be updated to point to the new commit.

The index is a staging area where the new commit is prepared. Essentially, the contents of the index are what will go into the new commit (though if you do git commit -a, this will automatically add all changes to files that Git knows about to the index before committing, so it will commit the current contents of your working tree). git add will add or update files from the working tree into your index.

Brian Campbell
Thanks a lot for the explanation Brian. So, the working tree contains all the uncommitted changes. If I commit my changes with git commit -a, then at that specific time my Working Tree and Index will be the same. When I push to my central repo, all three will be the same. Am I correct?
Vinod Mohan
@Vinod Pretty much. You can have files in your working tree that Git doesn't know about, and those won't be committed with `git commit -a` (you need to add them with `git add`), so your working tree may have extra files that your index, your local repo, or your remote repo do not have.
Brian Campbell
@Vinod: The working tree and index can become the same without committing (git add updates the index from the working tree, and git checkout <path> updates working tree from index). `HEAD` refers to the most recent commit, so when you commit, you are updating `HEAD` to your new commit, which matches the index. Pushing doesn't have much to do with it - it makes branches in the remote match branches in your local repo.
Jefromi
+1  A: 

The difference between HEAD (current branch or last committed state on current branch), index (aka. staging area) and working tree (the state of files in checkout) is described in "The Three States" section of the "3.1 Git Basics" chapter of Pro Git book by Scott Chacon (Creative Commons licensed).

Here is the image illustrating it from this chapter:

Local Operations - working directory vs. staging area (index) vs git repository (HEAD)

In the above image "working directory" is the same as "working tree", the "staging area" is alternate name for git "index", and HEAD points to currently checked branch, which tip points to last commit in the "git directory (repository)"

Note that git commit -a would stage changes and commit in one step.

Jakub Narębski
"A picture is worth a thousand words". Thanks Jakub.. And thanks for the link.
Vinod Mohan
+1  A: 

A few other good references on those topics:

alt text

I use the index as a checkpoint.
When I’m about to make a change that might go awry — when I want to explore some direction that I’m not sure if I can follow through on or even whether it’s a good idea, such as a conceptually demanding refactoring or changing a representation type — I checkpoint my work into the index.
If this is the first change I’ve made since my last commit, then I can use the local repository as a checkpoint, but often I’ve got one conceptual change that I’m implementing as a set of little steps.
I want to checkpoint after each step, but save the commit until I’ve gotten back to working, tested code.

alt text

They are basically named references for Git commits. There are two major types of refs: tags and heads.

  • Tags are fixed references that mark a specific point in history, for example v2.6.29.
  • On the contrary, heads are always moved to reflect the current position of project development.

alt text

Now we know what is happening in the project.
But to know what is happening right here, right now there is a special reference called HEAD. It serves two major purposes:

  • it tells Git which commit to take files from when you checkout, and
  • it tells Git where to put new commits when you commit.

When you run git checkout ref it points HEAD to the ref you’ve designated and extracts files from it. When you run git commit it creates a new commit object, which becomes a child of current HEAD. Normally HEAD points to one of the heads, so everything works out just fine.

alt text

VonC
Just look at all those pretty pictures!
Jefromi