О ветвлении в двух словах

Для точного понимания механизма ветвлений, необходимо вернуться назад и изучить то, как Git хранит данные.

Как вы можете помнить из раздела Снимки, а не различия, Git не хранит данные в виде последовательности изменений, он использует набор снимков (snapshot).

Когда вы фиксируете изменения, Git сохраняет коммит в виде объекта, который содержит указатель на снимок подготовленных данных. Этот объект так же содержит имя автора и email, сообщение и указатель на коммит или коммиты, непосредственно предшествующие данному (его родителей). У первоначального коммита родитель отсутствует, у обычного коммита есть один родитель, и есть несколько родителей для результатов слияния веток.

Предположим, у вас есть каталог с тремя файлами, вы добавляете их в индекс и создаете коммит. Во время индексации вычисляется контрольная сумма каждого файла (SHA-1 как вы узнали из Целостность Git), затем каждый файл сохраняется в репозиторий (Git называет такой файл blob — большой двоичный объект), а контрольная сумма попадет в индекс.

Когда вы фиксируете изменения, Git вычисляет контрольные суммы каждого подкаталога (в вашем случае это только основной каталог проекта) и сохраняет это в репозитории как объект дерева каталогов. Затем Git создает объект коммита с метаданными и указателем на основное дерево проекта для того, чтобы можно было воссоздать этот снимок в случае необходимости.

Ваш репозиторий Git теперь хранит пять объектов: три blob-объекта (по одному на каждый файл), объект дерева каталогов, содержащий список файлов и соответствующих им blob, а так же объект коммита, содержащий метаданные и указатель на объект дерева каталогов.

Если вы сделаете изменения и создадите еще один коммит, то он будет содержать указатель на предыдущий коммит.

Ветка в Git это простой перемещаемый указатель на один из этих коммитов. Имя основной ветки в Git по умолчанию — master. На следующем рисунке ветка master указывает на коммит 1038121.

Как только вы начнете создавать коммиты, ветка master будет всегда указывать на последний коммит. Каждый раз при создании коммита указатель ветки master будет передвигаться на следующий коммит автоматически.

Ветка master в Git — это не какая-то особенная ветка. Она точно такая же, как и все остальные ветки. Она существует почти во всех репозиториях только лишь потому, что ее создает Git, а большинство людей не меняют ее название.

Создать новую ветку

Что же на самом деле происходит, когда вы создаете ветку? Всего лишь создается новый указатель для дальнейшего перемещения.

Допустим, вы хотите создать новую ветку для реализации новой функциональности — issue-20. Вы можете это сделать в панели Навигатор, нажав Групповая разработка > Создать новую ветку... в контекстном меню проекта.

Выберите тип ветки — Feature и введите имя ветки — issue-20.

Стандартно при создании новой ветки 1C:EDT предлагает создать новую информационную базу с копией данных из основной ветки. Эти данные вы сможете использовать для отладки изменений в новой ветке. Таким образом больше в этом диалоге ничего менять не нужно и можно нажать Готово.

В результате создается новый указатель на тот же самый коммит, в котором вы находитесь.

На схеме это будет выглядеть следующим образом.

Как Git определяет, в какой ветке вы находитесь? Он хранит специальный указатель HEAD. Имейте в виду, что в Git концепция HEAD значительно отличается от других систем контроля версий, которые вы могли использовать раньше (Subversion или CVS). В Git это указатель на локальную ветку, в которой вы находитесь.

В вашем случае вы находитесь в ветке feature/issue-20, на нее указывает HEAD. Та ветка, на которую указывает HEAD, в панели История всегда выделяется жирным шрифтом, даже если она единственная, которая указывает на этот коммит.

Когда вы нажимаете Групповая разработка > Создать новую ветку... 1C:EDT не только создает новую ветку, но и сразу переключает вас на нее. В результате вы можете сразу начать работу над новой задачей.

Переключить ветки

Сейчас вы находитесь в ветке feature/issue-20.

На схеме это выглядит следующим образом.

Переключитесь на ветку master. Сделать это можно несколькими способами:

В результате указатель HEAD переместится на ветку master.

На схеме это будет выглядеть следующим образом.

Какой в этом смысл? Сделайте то, ради чего вы создавали новую ветку.

Переключитесь на ветку feature/issue-20, измените конфигурацию и зафиксируйте изменения. Как будто вы начали реализовывать задачу issue-20.

Это интересно, потому что указатель на вашу ветку feature/issue-20 переместился вперед, а master все еще указывает на тот коммит, где вы были в момент переключения веток.

Переключитесь назад на ветку master.

Возможная проблема: Чтобы видеть в панели История все ветки, а не только ветку, на которую указывает HEAD, включите в настройках панели фильтр refs/heads/**.

На схеме это будет выглядеть следующим образом.

Произошло две вещи. Указатель HEAD переместился назад на ветку master, а файлы в рабочем каталоге вернулись в то состояние, которое было сохранено в снимке, на который указывает ветка. Это также означает, что все изменения, вносимые с этого момента, будут отнесены к старой версии проекта. Другими словами, откатилась вся работа, выполненная в ветке feature/issue-20, а вы можете продолжать в другом направлении.

Совет: Переключение веток меняет файлы в рабочем каталоге. Важно запомнить, что когда вы переключаете ветки в Git, файлы в рабочем каталоге меняются. Если вы переключаетесь на старую ветку, то рабочий каталог будет выглядеть так же, как выглядел на момент последнего коммита в ту ветку. Если Git по каким-то причинам не может этого сделать, он не позволит вам переключиться.

Сделайте еще одно изменение и зафиксируйте его.

Теперь история вашего проекта разделилась. Вы создали ветку, переключились в нее, поработали, а затем вернулись в основную ветку и поработали в ней.

Эти изменения изолированы друг от друга: вы можете свободно переключаться туда и обратно, а когда будете готовы, можете слить их вместе. И все это делается простыми командами:
  • Групповая разработка > Переключить на и Групповая разработка > Коммит... или
  • Извлечь и Групповая разработка > Коммит....

Ветка в Git — это простой файл, содержащий 40 символов контрольной суммы SHA-1 коммита, на который она указывает; поэтому операции с ветками являются дешевыми с точки зрения потребления ресурсов или времени. Создание новой ветки в Git происходит так же быстро и просто как запись 41 байта в файл (40 знаков и перевод строки).

Это принципиально отличает процесс ветвления в Git от более старых систем контроля версий, где все файлы проекта копируются в другой подкаталог. В зависимости от размера проекта, операции ветвления в таких системах могут занимать секунды или даже минуты, когда в Git эти операции мгновенны. Поскольку при фиксации изменений Git сохраняет указатель на родительский коммит, то поиск подходящей базы для слияния веток делается автоматически и, в большинстве случаев, очень прост. Эти возможности побуждают разработчиков чаще создавать и использовать ветки.

Посмотрите, почему и вам имеет смысл делать так же.

По материалам книги Pro Git (авторы Scott Chacon и Ben Straub, издательство Apress). Книга распространяется по лицензии Creative Commons Attribution Non Commercial Share Alike 3.0 license.