

So now we have this: A <-B <-C <-D <- master (HEAD) The name stored in HEAD itself does not change at all: it's still master. Now that D exists, Git alters the hash ID stored under the name master, to store D's hash ID instead of C's. We will use D instead of the new hash ID since we don't know what the new hash ID will be: A <-B <-C <-D To make a new commit, Git packages up the index into a snapshot, saves that with your name and email address and so on, and includes the hash ID of commit C, to make a new commit with a new hash ID. (Since commit A is the very first commit ever, there is no earlier commit for it to point to, so it doesn't point anywhere at all, which makes it a bit special. This is how Git can turn the string HEAD into the correct hash ID: Git follows HEAD to master, then reads the hash ID out of master.) It's commit C itself that "points to"-retains the hash ID of-commit B, though and commit B points to commit A. (The name HEAD refers to the branch name, master. Here we say that the branch name master "points to" the third commit, which I have labeled C, rather than using one of Git's incomprehensible hash IDs like b06d364. Consider, for instance, this simple three-commit repository: A <-B <-C <- master (HEAD) We say that the new commit "points back to" the current commit. (This is why you must git add files: you copy them from your work-tree, where you have changed them, back into your index, so that they are ready to be "photographed" for the new snapshot.) Git also collects a commit message, and of course uses your name and email address and the current time, to make the new commit.īut Git also stores, in the new commit, the hash ID of the current commit. When you make a new commit by running git commit, Git takes the index contents and makes a permanent snapshot of everything that is in it right at that point. The presence of the index is a large part of what makes Git so fast: without it, Mercurial has to be extra-clever, and is still not as fast as Git.Ĭommits remember their parent new commits are children This is arguably a better design-but it's not the way Git works, so when using Git, you have an index. This is what Mercurial does this is why Mercurial does not need an index. The VCS could treat the work-tree as the "modifiable commit". 1ġIt's not necessary to have both the index and the work-tree. This is why they exist: the index is almost a "modifiable commit" (except that it's not saved until you run git commit), and the work-tree keeps the files in the form that the rest of the computer can use. What is in the index and work-tree, however, can be modified at any time. A commit is therefore permanent-or at least, permanent unless it is removed (which can be done but is difficult and usually undesirable). One other thing to remember about commits is that once a file is in a commit, it cannot be changed. The files stored in the index, and stored in each Git commit, do not have this form and are not usable by the compilers, interpreters, web-servers, and so on. If you write Java or Python code, or HTML for a web server, the work-tree files are usable by the compiler or interpreter or web-server. It's easy to see the work-tree: it has your files in their ordinary format, where you can view and edit them with all the regular tools on your computer. Git copies the files from HEAD into the index, and then from the index into the work-tree. Initially, the HEAD commit and the index normally match: they contain the same versions of all the committed files.

The point of this index is to act as an intermediate file-holder, situated between "the current commit" (aka HEAD) and the work-tree. In newer Git versions, you can use git worktree add to add additional work-trees each new work-tree comes with one new index/staging-area. This index is linked with the one work-tree. Note that each Git repository has just the one index, at least initially. This is also true of commits you obtain from someone else: they save the files that were in the other user's index at the time the other user ran git commit. Each commit also saves a complete snapshot of all the files you told it to: these are the files stored in your index (also known as your staging area) at the time you ran git commit. Commits, the index, and the work-treeĮach commit has several pieces of information, such as the author's name and email address and a time-stamp. This collection rarely shrinks: for the most part, the only thing you ever do with this collection of commits is add new commits. In fact, this is essentially what Git is about: it manages a collection of commits. The first thing to know here is that Git stores commits. The complicated parts come before and after.
