Статьи

Jump Start Git: ветвление в Git

jsgit

Ниже приведен небольшой отрывок из нашей книги « Jump Start Git» , доступный бесплатно для членов SitePoint Premium . Печатные копии продаются в магазинах по всему миру, или вы можете заказать их здесь . Мы надеемся, что вам понравится этот экстракт и вы найдете его полезным.

В главе 1 я говорил о своем единовременном страхе пробовать что-то новое в проекте. Что если я попробую что-то амбициозное, и оно сломает все, что работало раньше? Эта проблема решается использованием веток в Git.

Что такое филиалы?

Создание новой ветви в проекте означает создание новой копии этого проекта. Вы можете экспериментировать с этой копией, не затрагивая оригинал. Поэтому, если эксперимент не удался, вы можете просто отказаться от него и вернуться к оригиналу — master ветке.

Но если эксперимент успешен, Git позволяет легко включить экспериментальные элементы в master . И если на более позднем этапе вы передумаете, вы можете легко вернуться к состоянию проекта до этого слияния.

Так что ветка в Git — это самостоятельный путь развития. Вы можете создавать новые коммиты в ветви, не затрагивая другие ветви. Эта простота работы с ветками — одна из лучших функций Git. (Хотя другие варианты управления версиями, такие как CVS, имели такую ​​возможность ветвления, опыт объединения веток в CVS был очень утомительным. Если у вас был опыт работы с ветками в других системах контроля версий, будьте уверены, что работа с ветками в Git довольно разные.)

В Git вы попадаете в master ветку по умолчанию. Имя «мастер» не означает, что оно превосходит в любом случае. Это просто условность называть это так.

Примечание: отраслевые соглашения

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

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

Еще одно использование веток — это то, что они дают вам возможность работать над несколькими вещами одновременно, не мешая друг другу. Допустим, вы отправляете feature 1 на проверку, но вашему руководителю требуется некоторое время, чтобы ее рассмотреть. Между тем, вам нужно работать над feature 2 . В этом сценарии ветви вступают в игру. Если вы работаете над своей новой идеей в отдельной ветке, вы всегда можете переключиться назад на предыдущую ветку, чтобы вернуть хранилище в его предыдущее состояние, которое не содержит никакого кода, связанного с вашей идеей.

Давайте теперь начнем работать с ветками в Git. Чтобы увидеть список веток и текущую ветку, над которой вы работаете, выполните следующую команду:

 git branch 

Если вы клонировали свой репозиторий или настроили удаленный, вы также можете увидеть удаленные ветви. Просто добавьте -a к команде выше:

 git branch -a 
Команда, показывающая ветви в локальной копии, а также ветку происхождения

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

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

Создать филиал

Существуют различные способы создания ветки в Git. Чтобы создать новую ветку и остаться в текущей ветке, выполните следующее:

 git branch test_branch 

Здесь test_branch — это имя созданной ветви. Однако при запуске git branch кажется, что активная ветвь все еще является master ветвью. Чтобы изменить активную ветку, мы можем запустить команду checkout (показанную ниже):

 git checkout test_branch 
Создание новой ветки и активация

Создание новой ветки и активация

Вы также можете объединить две вышеупомянутые команды и, таким образом, создать и оформить новую ветку одной командой, добавив -b к команде checkout :

 git checkout -b new_test_branch 

Создать и оформить заказ на новую ветку одной командой

Ветви, которые мы только что создали, основаны на последнем коммите текущей активной ветки — в нашем случае это master . Если вы хотите создать ветку (скажем, old_commit_branch ) на основе определенного коммита, например cafb55d можете выполнить следующую команду:

 git checkout -b old_commit_branch cafb55d 
Создание ветки на основе старого коммита

Создание ветки на основе старого коммита

Чтобы переименовать текущую ветку в renamed_branch , выполните следующую команду:

 git branch -m renamed_branch 

Удалить ветку

Чтобы удалить ветку, выполните следующую команду:

 git branch -D new_test_branch 
Удаление ветки в Git

Удаление ветки в Git

Примечание: не удаляйте ветки, если нет необходимости

Поскольку на самом деле нет никаких недостатков в сохранении веток, в качестве меры предосторожности я бы предложил не удалять их, если количество ветвей в хранилище не станет слишком большим, чтобы его можно было контролировать.

Опция -D использованная выше, удаляет ветку, даже если она не была синхронизирована с удаленной веткой. Это означает, что если в текущей ветке у вас есть коммиты, которые еще не были отправлены, -D все равно удалит вашу ветку без предупреждения. Чтобы гарантировать, что вы не потеряете данные, вы можете добавить -d в качестве альтернативы -D . -d удаляет только ветку, если она была синхронизирована с удаленной веткой. Поскольку наши ветви еще не синхронизированы, давайте посмотрим, что произойдет, если мы добавим -d , как показано ниже:

Удаление ветки в Git с помощью опции -d

Как видите, Git выдает предупреждение и прерывает операцию, так как данные еще не были объединены с веткой.

Филиалы и HEAD

Теперь, когда у нас была возможность поэкспериментировать с основами ветвления, давайте потратим немного времени на обсуждение работы ветвей в Git, а также представим важную концепцию: HEAD .

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

Ветвь — это, по сути, указатель на коммит, который имеет родительский коммит, дедушкин коммит и так далее. Эта цепочка коммитов образует путь, о котором я упоминал выше. Как тогда вы связываете ветку и HEAD ? Ну, HEAD и кончик текущей ветви указывают на один и тот же коммит. Давайте посмотрим на диаграмму, чтобы проиллюстрировать эту идею:

Филиалы и ГОЛОВА

Филиалы и ГОЛОВА

Как показано выше, branch_A изначально является активной ветвью, а HEAD указывает на фиксацию C. Commit A является базовой фиксацией и не имеет родительской фиксации, поэтому коммиты в branch_A в обратном хронологическом порядке (что также формирует путь, по которому я речь branch_B о) C → B → A. branch_B в branch_B имеют вид E → D → B → A. HEAD указывает на последний коммит активного branch_A , который является коммитом C. Когда мы добавляем коммит, он добавляется в Активная ветка. После фиксации branch_A указывает на F, а ветвь следует за F → C → B → A, тогда как branch_B остается такой же. Теперь HEAD указывает на коммит F. Аналогично, изменения, когда мы добавляем еще один коммит, показаны на рисунке.

Расширенное ветвление: объединение ветвей

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

Мы создадим две новые ветви — new_feature и another_feature — и добавим несколько фиктивных коммитов. Проверка истории в каждой ветви показывает нам, что ветвь another_feature опережает один коммит, как показано ниже:

Проверка истории в каждой ветке

Проверка истории в каждой ветке

Эта ситуация может быть визуализирована, как показано ниже. Каждый круг представляет коммит, а имя ветви указывает на его HEAD (конец ветви).

Визуализация наших веток до слияния

Визуализация наших веток до слияния

Чтобы объединить new_feature с master , запустите следующее (предварительно убедившись, что master ветвь активна):

 git checkout master git merge new_feature 

Результат можно визуализировать, как показано ниже:

Состояние хранилища после слияния new_feature с master

Состояние хранилища после слияния new_feature с master

Чтобы объединить another_feature с new_feature , просто запустите следующее (убедитесь, что ветвь new_feature активна):

 git checkout new_feature git merge another_feature 

Результат можно визуализировать, как показано ниже:

Состояние репозитория после слияния another_feature с new_feature

Состояние репозитория после слияния another_feature с new_feature

Важно: следите за циклами

Диаграмма выше показывает, что это слияние создало цикл в истории вашего проекта для двух коммитов, где рабочие процессы расходились и сходились, соответственно. Работая индивидуально или в небольших группах, такие циклы могут не быть проблемой. Однако в большой команде, где со времени, когда вы отошли от основной ветки, было много коммитов, такие большие циклы затрудняют навигацию по истории и понимание изменений. Мы рассмотрим способ объединения ветвей без создания циклов с помощью команды rebase в главе 6.

Статус ветки new_feature после слияния

Статус ветки new_feature после слияния

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

Мы подробно обсудим конфликты в следующей главе. Ранее я упоминал, что ветки можно визуализировать простым путём коммитов. Когда мы объединяем ветки и не возникает конфликтов, как, например, выше, изменяется только путь ветки, а HEAD ветви обновляется. Это называется ускоренным слиянием.

Альтернативный способ слияния ветвей — это слияние без быстрой пересылки , добавив —no --no-ff к команде merge . Таким образом, в базовой ветви создается новый коммит с изменениями из другой ветви. Вам также предлагается указать сообщение о коммите:

 git merge --no-ff new_feature 

В приведенном выше примере первое (слияние new_feature с master ) было слиянием с ускоренной перемоткой вперед, а второе — слиянием без ускоренной перемотки с коммитом слияния.

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

Вывод

Что вы узнали?

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