О ветвлении в двух словах
Почти каждая система контроля версий в той или иной форме поддерживает ветвление. Используя ветвление, Вы отклоняетесь от основной линии разработки и продолжаете работу независимо от неё, не вмешиваясь в основную линию. Во многих системах контроля версий создание веток — это очень затратный процесс, часто требующий создания новой копии каталога с исходным кодом, что может занять много времени для большого проекта.
Некоторые люди, говоря о модели ветвления Git, называют её «киллер-фича», что выгодно выделяет Git на фоне остальных систем контроля версий. Что в ней такого особенного? Ветвление Git очень легковесно: операция создания ветки выполняется почти мгновенно, переключение между ветками туда-сюда, обычно, также быстро. В отличие от многих других систем контроля версий, Git поощряет процесс работы, при котором ветвление и слияние выполняется часто, даже по несколько раз в день. Понимание и владение этой функциональностью дает вам уникальный и мощный инструмент, который может полностью изменить привычный процесс разработки.
О ветвлении в двух словах
Для точного понимания механизма ветвлений, необходимо вернуться назад и изучить то, как Git хранит данные.
Как вы можете помнить из Что такое Git?, Git не хранит данные в виде последовательности изменений, он использует набор снимков (snapshot).
Когда вы делаете коммит, Git сохраняет его в виде объекта, который содержит указатель на снимок (snapshot) подготовленных данных. Этот объект так же содержит имя автора и email, сообщение и указатель на коммит или коммиты непосредственно предшествующие данному (его родителей): отсутствие родителя для первоначального коммита, один родитель для обычного коммита, и несколько родителей для результатов слияния двух и более веток.
Предположим, у вас есть каталог с тремя файлами и вы добавляете их все в индекс и создаёте коммит. Во время индексации вычисляется контрольная сумма каждого файла (SHA-1 как мы узнали из Что такое Git?), затем каждый файл сохраняется в репозиторий (Git называет такой файл блоб — большой бинарный объект), а контрольная сумма попадёт в индекс:
$ git add README test.rb LICENSE
$ git commit -m 'Initial commit'
Когда вы создаёте коммит командой git commit
, Git вычисляет контрольные суммы каждого подкаталога (в нашем случае, только основной каталог проекта) и сохраняет его в репозитории как объект дерева каталогов. Затем Git создаёт объект коммита с метаданными и указателем на основное дерево проекта для возможности воссоздать этот снимок в случае необходимости.
Ваш репозиторий Git теперь хранит пять объектов: три блоб объекта (по одному на каждый файл), объект дерева каталогов, содержащий список файлов и соответствующих им блобов, а так же объект коммита, содержащий метаданные и указатель на объект дерева каталогов.
Если вы сделаете изменения и создадите ещё один коммит, то он будет содержать указатель на предыдущий коммит.
Ветка в Git — это простой перемещаемый указатель на один из таких коммитов. По умолчанию, имя основной ветки в Git — master
. Как только вы начнёте создавать коммиты, ветка master
будет всегда указывать на последний коммит. Каждый раз при создании коммита указатель ветки master
будет передвигаться на следующий коммит автоматически.
Примечание
|
Ветка «master» в Git — это не какая-то особенная ветка. Она точно такая же, как и все остальные ветки. Она существует почти во всех репозиториях только лишь потому, что её создаёт команда |
Создание новой ветки
Что же на самом деле происходит при создании ветки? Всего лишь создаётся новый указатель для дальнейшего перемещения. Допустим вы хотите создать новую ветку с именем testing
. Вы можете это сделать командой git branch
:
$ git branch testing
В результате создаётся новый указатель на текущий коммит.
Как Git определяет, в какой ветке вы находитесь? Он хранит специальный указатель HEAD
. Имейте ввиду, что в Git концепция HEAD
значительно отличается от других систем контроля версий, которые вы могли использовать раньше (Subversion или CVS). В Git — это указатель на текущую локальную ветку. В нашем случае мы всё ещё находимся в ветке master
. Команда git branch
только создаёт новую ветку, но не переключает на неё.
Вы можете легко это увидеть при помощи простой команды git log
, которая покажет вам куда указывают указатели веток. Эта опция называется --decorate
.
$ git log --oneline --decorate
f30ab (HEAD -> master, testing) Add feature #32 - ability to add new formats to the central interface
34ac2 Fix bug #1328 - stack overflow under certain conditions
98ca9 Initial commit
Здесь можно увидеть указывающие на коммит f30ab
ветки: master
и testing
.
Переключение веток
Для переключения на существующую ветку выполните команду git checkout
. Давайте переключимся на ветку testing
:
$ git checkout testing
В результате указатель HEAD
переместится на ветку testing
.
Какой в этом смысл? Давайте сделаем ещё один коммит:
$ vim test.rb
$ git commit -a -m 'made a change'
Интересная ситуация: указатель на ветку testing
переместился вперёд, а master
указывает на тот же коммит, где вы были до переключения веток командой git checkout
. Давайте переключимся назад на ветку master
:
$ git checkout master
Примечание
|
git log не показывает все ветки по умолчаниюЕсли выполнить команду Ветка никуда не исчезла; просто Git не знает, что именно она вас интересует, и выводит наиболее полезную по его мнению информацию. Другими словами, по умолчанию Для просмотра истории коммитов другой ветки необходимо явно указать её имя: |
Эта команда сделала две вещи: переместила указатель HEAD
назад на ветку master
и вернула файлы в рабочем каталоге в то состояние, на снимок которого указывает master
. Это также означает, что все вносимые с этого момента изменения будут относиться к старой версии проекта. Другими словами, вы откатили все изменения ветки testing
и можете продолжать в другом направлении.
Примечание
|
Переключение веток меняет файлы в рабочем каталоге
Важно запомнить, что при переключении веток в Git происходит изменение файлов в рабочем каталоге. Если вы переключаетесь на старую ветку, то рабочий каталог будет выглядеть так же, как выглядел на момент последнего коммита в ту ветку. Если Git по каким-то причинам не может этого сделать — он не позволит вам переключиться вообще. |
Давайте сделаем ещё несколько изменений и создадим очередной коммит:
$ vim test.rb
$ git commit -a -m 'made other changes'
Теперь история вашего проекта разошлась (см Разветвлённая история). Вы создали ветку и переключились на неё, поработали, а затем вернулись в основную ветку и поработали в ней. Эти изменения изолированы друг от друга: вы можете свободно переключаться туда и обратно, а когда понадобится — объединить их. И всё это делается простыми командами: branch
, checkout
и commit
.
Все описанные действия можно визуализировать с помощью команды git log
. Для отображения истории коммитов, текущего положения указателей веток и истории ветвления выполните команду git log --oneline --decorate --graph --all
.
$ git log --oneline --decorate --graph --all
* c2b9e (HEAD, master) Made other changes
| * 87ab2 (testing) Made a change
|/
* f30ab Add feature #32 - ability to add new formats to the central interface
* 34ac2 Fix bug #1328 - stack overflow under certain conditions
* 98ca9 initial commit of my project
Ветка в Git — это простой файл, содержащий 40 символов контрольной суммы SHA-1 коммита, на который она указывает; поэтому операции с ветками являются дешёвыми с точки зрения потребления ресурсов или времени. Создание новой ветки в Git происходит так же быстро и просто как запись 41 байта в файл (40 знаков и перевод строки).
Это принципиально отличает процесс ветвления в Git от более старых систем контроля версий, где все файлы проекта копируются в другой подкаталог. В зависимости от размера проекта, операции ветвления в таких системах могут занимать секунды или даже минуты, когда в Git эти операции мгновенны. Поскольку при коммите мы сохраняем указатель на родительский коммит, то поиск подходящей базы для слияния веток делается автоматически и, в большинстве случаев, очень прост. Эти возможности побуждают разработчиков чаще создавать и использовать ветки.
Давайте посмотрим, почему и вам имеет смысл делать так же.
Примечание
|
Одновременное создание новой ветки и переключение на неё
Как правило, при создании новой ветки вы хотите сразу на неё переключиться — это можно сделать используя команду |
Примечание
|
Начиная с Git версии 2.23, вы можете использовать
|
No Comments