Git branches are “light” because they are just pointers: git simply points to “host” or “development” or “trunk” or “myfeature” to a specific commit. When you make an update on a branch, the pointer advances. Consider this diagram from git -scm docs, a star resource on this.

The "master" section of this diagram indicates commit f30ab . In the "testing" branch, the c2b9e commit is c2b9e . HEAD in this diagram is a special pointer: most of the time it points to another branch (in git terminology, this is a "symbolic link") to show the current state of health of the directory. When you say, say, git checkout f30ab , you put the repository in a detached HEAD state. In other words, you move the pointer from a symbolic link, "testing", to commit, f30ab .
Take, for example, one that you can configure yourself.
git init /tmp/test && cd /tmp/test ;
Now you have something like below. I don't have omnigraffle, so we are stuck with a directed graph:
* 93e71ee - (HEAD, development) third commit / * 6378754 - (master) second commit * d2b4ba9 - first commit
As you can conclude from parentheses, "master" points to commit 6378754 , "development" points to commit 93e71ee and HEAD points to "development". Do not take my word for it. Explore the signs yourself:
$ cat .git/refs/heads/master ;
When branches are just pointers, the transition between them is trivial. One particular case is HEAD . Think about what happens when we check the wizard:
$ git checkout master ;
How about a commit check?
$ git checkout d2b4ba9 ;
What does this advice mean? It, which commits against the repository in the "stand-alone HEAD" state, generates errors that are inaccessible from any branch. When HEAD changes (from any validation operation, such as git checkout master ), these commits will be lost. This is easier to see on the chart:
echo D > D ;
Let's look at our schedule. Note. The no git command generates what you see below. I modified the existing output for the purposes of this example.
* 93e71ee - (development) third commit / * 6378754 - (master) second commit / * / 72c1f03 - (HEAD) fourth commit |/ * d2b4ba9 - first commit
HEAD is still disconnected. He points to 72c1f03 . "master" and "development", where we expect, but 72c1f03 not available from any branch. This is problem. If I want to keep 72c1f03 around, I have to give it a branch:
$ git checkout -b experimental ;
And the schedule:
* 93e71ee - (development) third commit / * 6378754 - (master) second commit / * / 72c1f03 - (HEAD, experimental) fourth commit |/ * d2b4ba9 - first commit
Git simplifies branching. Tapping and pulling pointer information is much faster than tapping and pulling entire sets of files. Cutting a branch takes milliseconds. It is so easy that it almost feels wrong. As a result, git allows for more distributed workflow options , although it, of course, can also handle centralized ones.