Ниже приведен небольшой отрывок из нашей книги « 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
Примечание: не удаляйте ветки, если нет необходимости
Поскольку на самом деле нет никаких недостатков в сохранении веток, в качестве меры предосторожности я бы предложил не удалять их, если количество ветвей в хранилище не станет слишком большим, чтобы его можно было контролировать.
Опция -D
использованная выше, удаляет ветку, даже если она не была синхронизирована с удаленной веткой. Это означает, что если в текущей ветке у вас есть коммиты, которые еще не были отправлены, -D
все равно удалит вашу ветку без предупреждения. Чтобы гарантировать, что вы не потеряете данные, вы можете добавить -d
в качестве альтернативы -D
. -d
удаляет только ветку, если она была синхронизирована с удаленной веткой. Поскольку наши ветви еще не синхронизированы, давайте посмотрим, что произойдет, если мы добавим -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
Результат можно визуализировать, как показано ниже:
Чтобы объединить another_feature
с new_feature
, просто запустите следующее (убедитесь, что ветвь new_feature
активна):
git checkout new_feature git merge another_feature
Результат можно визуализировать, как показано ниже:
Важно: следите за циклами
Диаграмма выше показывает, что это слияние создало цикл в истории вашего проекта для двух коммитов, где рабочие процессы расходились и сходились, соответственно. Работая индивидуально или в небольших группах, такие циклы могут не быть проблемой. Однако в большой команде, где со времени, когда вы отошли от основной ветки, было много коммитов, такие большие циклы затрудняют навигацию по истории и понимание изменений. Мы рассмотрим способ объединения ветвей без создания циклов с помощью команды rebase
в главе 6.
Это слияние произошло без каких-либо «конфликтов». Простая причина этого заключается в том, что в ветку new_feature
не было добавлено никаких новых new_feature
по сравнению с веткой another_feature
. Конфликты в Git происходят, когда один и тот же файл был изменен в нечастых фиксациях в обеих ветках. Git вызывает конфликт, чтобы убедиться, что вы не потеряете данные.
Мы подробно обсудим конфликты в следующей главе. Ранее я упоминал, что ветки можно визуализировать простым путём коммитов. Когда мы объединяем ветки и не возникает конфликтов, как, например, выше, изменяется только путь ветки, а HEAD
ветви обновляется. Это называется ускоренным слиянием.
Альтернативный способ слияния ветвей — это слияние без быстрой пересылки , добавив —no --no-ff
к команде merge
. Таким образом, в базовой ветви создается новый коммит с изменениями из другой ветви. Вам также предлагается указать сообщение о коммите:
git merge --no-ff new_feature
В приведенном выше примере первое (слияние new_feature
с master
) было слиянием с ускоренной перемоткой вперед, а второе — слиянием без ускоренной перемотки с коммитом слияния.
Несмотря на то, что стиль быстрой пересылки слияний используется по умолчанию, обычно рекомендуется использовать метод без быстрой пересылки слияний в основную ветвь. В долгосрочной перспективе может быть полезен новый коммит, который идентифицирует слияние новых функций, поскольку он логически разделяет часть кода, отвечающую за новую функцию, на коммит.
Вывод
Что вы узнали?
В этой главе мы обсудили, что такое ветки и как ими управлять в Git. Мы смотрели на создание, изменение, удаление и объединение веток.