Представьте себе каталог, который содержит дерево файлов, и вы подготавливаете их все вместе, а затем сохраняете в виде одного коммита. В процессе подготовки вычисляется контрольная сумма каждого файла (SHA-1 как мы узнали из Введение), хранящая версию файла в репозитории Git (Git ссылается на них), затем эти контрольные суммы добавляются в область подготовленных файлов:
$git add README test.rb LICENSE
$git commit -m 'initial commit of my project'
Когда вы создаете коммит командой git commit, Git вычисляет контрольные суммы каждого подкаталога (в нашем случае, только основной каталог проекта) и сохраняет эти объекты дерева в репозитории. Затем Git создает объект коммита с метаданными и указателем на основное дерево проекта для возможности воссоздать этот снимок (snapshot) в случае необходимости.
Ваш репозиторий Git теперь хранит пять объектов: блоб (blob) для содержимого каждого файла, содержимое каталога в виде дерева с указателями на блобы сохраненных фалов, сам коммит с указателем на основное дерево, метаданные коммита.

Рисунок 1. Коммит и его дерево
Если вы сделаете изменения и еще один коммит, тогда следующий коммит сохранит указатель на коммит, предшествующий ему.

Рисунок 2. Коммит и его родители
Ветка (branch) в Git — это легко перемещаемый указатель на один из этих коммитов. Имя основной ветки по умолчанию в Git — master.
Когда вы делаете коммиты, то получаете основную ветку, указывающую на ваш последний коммит. Каждый коммит автоматически двигает этот указатель вперед.
Ветка “master” в Git — это не специальная ветка. Она точно такая же, как и все остальные ветки. Она существует почти во всех репозиториях только лишь потому, что ее создает команда git init, а большинство людей не меняют ее название.

Рисунок 3. Ветка и история коммитов
Что же на самом деле происходит, когда вы создаете ветку? Всего лишь создается новый указатель для дальнейшего перемещения. Допустим вы хотите создать новую ветку с именем “testing” Вы можете это сделать командой git branch :
$git branch testing
В результате создается новый указатель на тот же самый коммит, в котором вы находитесь.

Рисунок 4. Две ветки указывают на одну и ту же последовательность коммитов
Как Git определяет, в какой ветке вы находитесь? Он хранит специальный указатель HEAD. Имейте ввиду, что в Git концепция HEAD значительно отличается от других систем контроля версий, которые вы могли использовать раньше (Subversion или CVS). В Git это указатель на локальную ветку, в которой вы находитесь. В нашем случае мы все еще находимся в ветке “master”. Команда git branch только создает новую ветку. Переключения не происходит.

Рисунок 5. HEAD указывает на ветку
Вы можете легко это увидеть при помощи простой команды git log. Она покажет вам, куда указывают указатели веток. Эта опция называется --decorate.
$git log --oneline --decorate
f30ab (HEAD, master, testing) add feature #32 - ability to add new
34ac2 fixed bug #1328 - stack overflow under certain conditions
98ca9 initial commit of my project
Видны ветки “master” и “testing”, которые указывают на коммит f30ab.
Чтобы переключиться на существующую ветку, выполните команду git checkout. Давайте переключимся на ветку “testing”:
$git checkout testing
В результате указатель HEAD переместится на ветку testing.

Рисунок 6. HEAD указывает на текущую ветку
Какой в этом смысл? Давайте сделаем еще один коммит:
$vim test.rb
$git commit -a -m 'made a change'

Рисунок 7. Указатель на ветку HEAD переместился вперед после коммита
Это интересно, потому что указатель на вашу ветку “testing” переместился вперед, а “master” все еще указывает на тот коммит, где вы были в момент выполнения команды git checkout для переключения веток. Давайте переключимся назад на ветку “master”:
Читать дальше