Почти каждая система контроля версий (СКВ) в какой-то форме поддерживает ветвление. Используя ветвление, Вы отклоняетесь от основной линии разработки и продолжаете работу независимо от неё, не вмешиваясь в основную линию. Во многих СКВ создание веток — это очень затратный процесс, часто требующий создания новой копии каталога с исходным кодом, что может занять много времени для большого проекта.
Некоторые люди, говоря о модели ветвления Git, называют ее «киллер-фича», что выгодно выделяет Git на фоне остальных СКВ. Что в ней такого особенного? Ветвление Git очень легковесно: операция создания ветки выполняется почти мгновенно, переключение между ветками туда-сюда, обычно, также быстро. В отличие от многих других СКВ, Git поощряет процесс работы, при котором ветвление и слияние выполняется часто, даже по несколько раз в день. Понимание и владение этой функциональностью дает вам уникальный и мощный инструмент, который может полностью изменить привычный процесс разработки.
О ветвлении в двух словах
Для точного понимания механизма ветвлений, необходимо вернуться назад и изучить то, как Git хранит данные.
Как вы можете помнить из Что такое Git?, Git не хранит данные в виде последовательности изменений, он использует набор снимков (snapshot).
Когда вы делаете коммит, Git сохраняет его в виде объекта, который содержит указатель на снимок (snapshot) подготовленных данных. Этот объект так же содержит имя автора и email, сообщение и указатель на коммит или коммиты непосредственно предшествующие данному (его родителей): отсутствие родителя для первоначального коммита, один родитель для обычного коммита, и несколько родителей для результатов слияния двух и более веток.
Предположим, у вас есть каталог с тремя файлами и вы добавляете их все в индекс и создаёте коммит. Во время индексации вычисляется контрольная сумма каждого файла (SHA-1 как мы узнали из Что такое Git?), затем каждый файл сохраняется в репозиторий (Git называет такой файл блоб — большой бинарный объект), а контрольная сумма попадёт в индекс:
Ваш репозиторий Git теперь хранит пять объектов: три блоб объекта (по одному на каждый файл), объект дерева каталогов, содержащий список файлов и соответствующих им блобов, а так же объект коммита, содержащий метаданные и указатель на объект дерева каталогов.
Если вы сделаете изменения и создадите ещё один коммит, то он будет содержать указатель на предыдущий коммит.
Создание новой ветки
В результате создаётся новый указатель на текущий коммит.
Переключение веток
Какой в этом смысл? Давайте сделаем ещё один коммит:
Если выполнить команду git log прямо сейчас, то в её выводе только что созданная ветка «testing» фигурировать не будет.
Ветка никуда не исчезла; просто Git не знает, что именно она вас интересует, и выводит наиболее полезную по его мнению информацию. Другими словами, по умолчанию git log отобразит историю коммитов только для текущей ветки.
Важно запомнить, что при переключении веток в Git происходит изменение файлов в рабочем каталоге. Если вы переключаетесь на старую ветку, то рабочий каталог будет выглядеть так же, как выглядел на момент последнего коммита в ту ветку. Если Git по каким-то причинам не может этого сделать — он не позволит вам переключиться вообще.
Давайте сделаем еще несколько изменений и создадим очередной коммит:
Ветка в Git — это простой файл, содержащий 40 символов контрольной суммы SHA-1 коммита, на который она указывает; поэтому операции с ветками являются дешёвыми с точки зрения потребления ресурсов или времени. Создание новой ветки в Git происходит так же быстро и просто как запись 41 байта в файл (40 знаков и перевод строки).
Это принципиально отличает процесс ветвления в Git от более старых систем контроля версий, где все файлы проекта копируются в другой подкаталог. В зависимости от размера проекта, операции ветвления в таких системах могут занимать секунды или даже минуты, когда в Git эти операции мгновенны. Поскольку при коммите мы сохраняем указатель на родительский коммит, то поиск подходящей базы для слияния веток делается автоматически и, в большинстве случаев, очень прост. Эти возможности побуждают разработчиков чаще создавать и использовать ветки.
Давайте посмотрим, почему и вам имеет смысл делать так же.
Перемещение по веткам и коммитам в Git
Перевод статьи «Git Switch Branch – How to Change the Branch in Git».
Пользуясь Git, вам очень часто придется перемещаться по веткам. Для этого используется команда git checkout.
Как создать новую ветку в Git и перейти в нее
Допустим, вы находитесь в ветке master :
Как перейти в уже существующую ветку в Git
Для перехода в предыдущую ветку (т. е. ту, из которой вы перешли в текущую) можно передать команде git checkout не имя ветки, а просто дефис:
Как переместиться к определенному коммиту
Ветки по сути являются просто указателями трекерами отдельных коммитов в истории Git.
Как найти SHA коммита
Один из способов найти SHA коммита — просмотреть лог Git. Делается это при помощи команды git log :
В первой строке каждого коммита после слова commit есть длинная строка букв и цифр: 94ab1fe28727…
Вот она и называется SHA. Это уникальный идентификатор, генерируемый для каждого коммита.
Чтобы перейти к определенному коммиту, вам нужно лишь передать его SHA в качестве параметра команды git checkout :
Примечание: обычно можно использовать всего несколько первых символов SHA, потому что первые 4-5 символов скорее всего образуют уникальную комбинацию в рамках проекта.
Что такое detached HEAD (отсоединенный указатель HEAD)?
В результате перехода к конкретному коммиту вы указываетесь в «состоянии отсоединенного указателя HEAD» (« detached HEAD state »).
[a detached HEAD state] означает, что HEAD направлен на конкретный коммит, а не на именованную ветку.
В общем, HEAD (один из внутренних указателей Git, отслеживающий, где именно в истории Git вы находитесь) отклонился от известных веток, так что все изменения с этого момента будут формировать новый путь в истории Git. Поэтому Git хочет убедиться, что вы именно этого хотите, и в выводе предлагает вам пространство для экспериментов:
«Вы в состоянии detached HEAD. Можете осмотреться, внести какие-нибудь экспериментальные изменения и закоммитить их. Если затем вы переключитесь обратно на ветку, вы сбросите все коммиты, сделанные в этом состоянии, никак не задев никакие ветки».
Исходя из этого, у вас есть два варианта:
Заключение
Команда git checkout — очень полезная и многофункциональная. С ее помощью можно создавать новые ветки, перемещаться по веткам и коммитам и т. д.
Основы ветвления и слияния
Давайте рассмотрим простой пример рабочего процесса, который может быть полезен в вашем проекте. Ваша работа построена так:
Вы работаете над сайтом.
Вы создаете ветку для новой статьи, которую вы пишете.
Вы работаете в этой ветке.
В этот момент вы получаете сообщение, что обнаружена критическая ошибка, требующая скорейшего исправления. Ваши действия:
Переключиться на основную ветку.
Создать ветку для добавления исправления.
После тестирования слить ветку содержащую исправление с основной веткой.
Переключиться назад в ту ветку, где вы пишете статью и продолжить работать.
Основы ветвления
Предположим, вы работаете над проектом и уже имеете несколько коммитов.
Это то же самое что и:
Вы работаете над своим сайтом и делаете коммиты. Это приводит к тому, что ветка iss53 движется вперед, так как вы переключились на нее ранее ( HEAD указывает на нее).
Но перед тем как сделать это — имейте в виду, что если рабочий каталог либо индекс содержат незафиксированные изменения, конфликтующие с веткой, на которую вы хотите переключиться, то Git не позволит переключить ветки. Лучше всего переключаться из чистого рабочего состояния проекта. Есть способы обойти это (припрятать изменения (stash) или добавить их в последний коммит (amend)), но об этом мы поговорим позже в разделе Припрятывание и очистка главы 7. Теперь предположим, что вы зафиксировали все свои изменения и можете переключиться на ветку master :
С этого момента ваш рабочий каталог имеет точно такой же вид, какой был перед началом работы над проблемой #53, и вы можете сосредоточиться на работе над исправлением. Важно запомнить: когда вы переключаете ветки, Git возвращает состояние рабочего каталога к тому виду, какой он имел в момент последнего коммита в эту ветку. Он добавляет, удаляет и изменяет файлы автоматически, чтобы состояние рабочего каталога соответствовало тому, когда был сделан последний коммит.
Теперь вы можете перейти к написанию исправления. Давайте создадим новую ветку для исправления, в которой будем работать, пока не закончим исправление.
Вы можете прогнать тесты, чтобы убедиться, что ваше исправление делает именно то, что нужно. И если это так — выполнить слияние ветки hotfix с веткой master для включения изменений в продукт. Это делается командой git merge :
Теперь вы можете переключиться обратно на ветку iss53 и продолжить работу над проблемой #53:
Основы слияния
Вместо того, чтобы просто передвинуть указатель ветки вперёд, Git создаёт новый результирующий снимок трёхстороннего слияния, а затем автоматически делает коммит. Этот особый коммит называют коммитом слияния, так как у него более одного предка.
Теперь, когда изменения слиты, ветка iss53 больше не нужна. Вы можете закрыть задачу в системе отслеживания ошибок и удалить ветку:
Основные конфликты слияния
Git не создал коммит слияния автоматически. Он остановил процесс до тех пор, пока вы не разрешите конфликт. Чтобы в любой момент после появления конфликта увидеть, какие файлы не объединены, вы можете запустить git status :
Всё, где есть неразрешённые конфликты слияния, перечисляется как неслитое. В конфликтующие файлы Git добавляет специальные маркеры конфликтов, чтобы вы могли исправить их вручную. В вашем файле появился раздел, выглядящий примерно так:
Мы рассмотрим более продвинутые инструменты для разрешения сложных конфликтов слияния в разделе Продвинутое слияние главы 7.
Если это вас устраивает и вы убедились, что все файлы, где были конфликты, добавлены в индекс — выполните команду git commit для создания коммита слияния. Комментарий к коммиту слияния по умолчанию выглядит примерно так:
Если вы считаете, что коммит слияния требует дополнительных пояснений — опишите как были разрешены конфликты и почему были применены именно такие изменения, если это не очевидно.
Git checkout
Переключение веток аналогично переключению старых коммитов и файлов, в которых рабочий каталог обновляется в соответствии с выбранной веткой/ревизией; вместе с тем новые изменения сохраняются в истории проекта, то есть это не просто операция чтения.
Переключение веток
Наличие выделенной ветки для каждой новой функции сильно отличается от традиционного рабочего процесса в SVN. Это значительно облегчает проведение новых экспериментов без страха разрушить существующую функциональность и позволяет одновременно работать со множеством несвязанных функций. Кроме того, ветки облегчают ведение нескольких совместных рабочих процессов.
Использование: существующие ветки
В вышеприведенном примере показано, как просмотреть список доступных веток с помощью команды git branch и переключиться на конкретную ветку (в данном случае — на ветку feature_inprogress_branch ).
Новые ветки
Переключение веток
Переключение на удаленную ветку
При совместной работе команды нередко используют удаленные репозитории. Такие репозитории могут размещаться на сервере с предоставлением общего доступа либо это может быть локальная копия другого коллеги. Каждый удаленный репозиторий содержит собственный набор веток. Для переключения на удаленную ветку нужно сначала извлечь содержимое этой ветки.
В современных версиях Git переключение на удаленную ветку не отличается от переключения на локальную ветку.
В старых версиях Git необходимо создавать новую ветку на основе удаленного репозитория ( remote ).
Кроме того, можно переключиться на новую локальную ветку и сбросить ее до последнего коммита удаленной ветки.
Открепленные указатели HEAD
Резюме
Готовы попробовать ветвление?
Ознакомьтесь с этим интерактивным обучающим руководством.
Git branch
В этом документе подробно описывается команда git branch и рассматривается общая модель ветвления в Git. Возможность ветвления доступна в большинстве современных систем контроля версий. Однако эта операция в ряде систем может быть довольно затратной как по времени, так и по объему дискового пространства. В Git ветки — это элемент повседневного процесса разработки. По сути ветки в Git представляют собой указатель на снимок изменений. Если нужно добавить новую возможность или исправить ошибку (незначительную или серьезную), вы создаете новую ветку, в которой будут размещаться эти изменения. Объединить нестабильный код с основной базой кода становится сложнее, к тому же перед слиянием с основной веткой можно очистить историю работы над возможностью.
Git предлагает облегченную реализацию веток по сравнению с другими системами контроля версий. Вместо того чтобы копировать файлы из каталога в каталог, Git хранит ветку в виде ссылки на коммит. Получается, что ветка представляет собой вершину серии коммитов, а не контейнер для коммитов. История ветки распространяется через иерархические отношения с другими коммитами.
Во время чтения помните, что ветки в Git не похожи на ветки в SVN. Ветки в SVN используются только для фиксации периодических крупномасштабных наработок, а ветки в Git являются неотъемлемой частью повседневного рабочего процесса. Далее приводится более подробное описание внутренней архитектуры ветвления в Git.
Порядок действий
Ветка представляет собой отдельное направление разработки. Ветки выступают в качестве абстрактного представления для процесса редактирования/индексации/коммита. Можно рассматривать их как способ запросить новый рабочий каталог, раздел проиндексированных файлов и историю проекта. Новые коммиты записываются в историю текущей ветки, что приводит к образованию развилки в истории проекта.
Распространенные опции
Удаление указанной ветки. Это «безопасная» операция, поскольку Git не позволит удалить ветку, если в ней есть неслитые изменения.
Принудительное удаление указанной ветки, даже если в ней есть неслитые изменения. Эта команда используется, если вы хотите навсегда удалить все коммиты, связанные с определенным направлением разработки.
Вывод списка всех удаленных веток.
Создание веток
Важно понимать, что ветки — это просто указатели на коммиты. Когда вы создаете ветку, Git просто создает новый указатель. Репозиторий при этом никак не изменяется. Допустим, вы начинаете работать с репозиторием, который выглядит так:
Затем вы создаете новую ветку с помощью следующей команды.
История репозитория остается неизменной. Все, что вы получаете, — это новый указатель на текущий коммит:
Создание удаленных веток
До сих пор все эти примеры демонстрировали работу с локальными ветками. Команда git branch работает и с удаленными ветками. Для выполнения операций на удаленных ветках сначала необходимо настроить удаленный репозиторий и добавить его в конфигурацию локального репозитория.
Удаление веток
После того как вы завершите работу в ветке и сольете ее с основной базой кода, эту ветку можно будет удалить без потери истории:
Однако, если ветка не была слита, указанная выше команда выдаст сообщение об ошибке:
Эта команда удаляет ветку независимо от ее состояния и не выдает никаких предупреждений, поэтому используйте ее с осторожностью.
Предыдущие команды удаляют локальную копию ветки, но ветка может сохраниться в удаленных репозиториях. Для удаления ветки из удаленного репозитория выполните следующую команду.
Резюме
По сравнению с другими системами контроля версий, операции с ветками в Git являются экономичными и используются часто. Такая гибкость позволяет эффективно настроить рабочий процесс в Git. Дополнительную информацию о рабочих процессах в Git см. на наших страницах, где подробно обсуждаются: рабочий процесс с функциональными ветками, рабочий процесс Git-flow и рабочий процесс с форками.
Готовы попробовать ветвление?
Ознакомьтесь с этим интерактивным обучающим руководством.





















