Предыдущий ролик Следующий ролик  

Видео урок: Использование быстрого и настоящего слияния

Git: обучение основам

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

Мы создали бранч, мы сделали коммит в этот бранч, но мы не сделали никаких изменений в основной бранч, и как результат, у нас получилось быстрое слияние. Возможно, вы заметили, а, возможно, и нет, но Git на самом деле сказал нам о сделанном слиянии. Что происходит, когда Git собирается сделать слияние? Он берет все то, что у вас есть, начиная с конца, берет всех предков и возвращается к самому началу. В нашем примере он начинает с ba8ce, а затем переходит к 534de и далее по цепочке, чтобы добраться до 84c46a.

Попутно Git смотрит, есть ли у него указатель HEAD текущего основного бранча. В нашем случае HEAD указывал на коммит, где был сделан бранч, не было сделано никакого перемещения. Если Git увидит в цепочке HEAD, он скажет - о, я спокойно могу сделать быстрое слияние. Я не хочу делать этого слияния и создавать новый коммит, вместо этого я просто могу переместить коммит вверх и переместить на него HEAD. Теперь revise_navigation также указывает на ту же вещь, оба бранча указывают на ba8ce.

Нет никакой необходимости делать новый коммит. Можно просто пройти по цепочке и сделать быстрое слияние. Мы знаем, что все верно, потому что мы можем написать git log seo_title --oneline, и давайте посмотрим на эти три строки. Обратите внимание, что верхний коммит здесь - это dc9c83c, это то, что было изменено до этого в seo_title, и это изменение мы отправили в master. Теперь давайте взглянем на master. Видите, здесь те же самые коммиты, тот же самый SHA, тот же самый объект сохранен в Git.

Git не делает новый коммит, чтобы объединить эти два бранча, он делает быстрое слияние. Есть также несколько опций, связанных с быстрым слиянием. Первая - это опция no-ff, то есть git merge --no-ff, а затем имя бранча, от которого вы хотите сделать слияние. Опция no-ff заставляет Git создать коммит слияния. Она говорит - не делай быстрое слияние, создай новый коммит с сообщением. Вы можете захотеть сделать это, потому что вам нужно задокументированное подтверждение того, что вы провели слияние.

Вы не хотите, чтобы слияние прошло тихо, вы хотите получить логи этого действия. Вторая опция, о которой вам следует знать, - это опция ff-only. Не смущайтесь, no-ff говорит не делать быстрого слияния, ff-only говорит сделать слияние, только если оно и будет быстрым. Если вы не можете сделать быстрое слияние, то тогда процесс просто оборвется. Даже не пытайтесь провести его, просто выйдите. Мы не будем на данный момент использовать ни одну из этих опций, но о них стоит знать. А теперь, в качестве примера, давайте попробуем сделать реальное слияние, или небыстрое слияние.

Давайте взглянем на наши бранчи, мы уже сделали слияние нашего бранча seo_title. Теперь я хочу сделать слияние бранча shorten_title и внести эти изменения. Если бы мы сделали слияние так, как и ранее, git merge shorten_title, произошло бы быстрое слияние. Почему же так происходит? А потому что единственное различие между бранчами заключается в том, что в shorten_title есть коммит, которого нет в основном бранче. Было два коммита, которых до сих пор не было в основном бранче, теперь один коммит уже есть и здесь, так что будет произведено быстрое слияние. Вместо этого мы не хотим делать быстрое слияние, и для этого нам нужно отправить коммит в основной бранч.

Если в основном бранче появится коммит, тогда Git не сможет сделать быстрое слияние, потому что теперь HEAD переместится на новый коммит, который не находится в бранче shorten_title. Давайте попробуем. Нужно убедиться, что мы находимся в основном бранче, а теперь давайте отредактируем contact.html, тут написано Export California: Contact Us, давайте уберем us, чтобы осталось только Contact. Закрываем, чистим экран, пишем git status, файл с контактами на месте, git add contact.html, git commit -m и "Edit contact.html title".

Итак, вот наш коммит сделан, git log --oneline -3, давайте взглянем, все на месте. Теперь у нас есть новый коммит, который идет после коммита dc9, пишем git log для бранча shorten_title, и давайте быстренько посмотрим на логи. Видите, коммит на месте, но после него идут еще два коммита. То есть, у нас есть общий предок, но прямо сейчас HEAD указывает сюда, и это не один из предков бранча shorten_title. Таким образом, это не будет быстрое слияние, это будет настоящее слияние. Процесс такой же.

Мы просто прописываем git merge shorten_title. Теперь Git просит меня написать сообщение для коммита, это потому что сделал настройку, что TextMate является текстовым редактором по умолчанию. Возможно, он настроен на другой редактор, или он настроен так, что у вас вообще нет возможности редактировать сообщения, так что Git делает коммит с этим сообщением - Merge branch shorten_title. Все эти строки будут игнорироваться и не попадут в сообщение для коммита. Я это принимаю, нажимаю Save и закрываю, Git говорит - Merge made by the recursive strategy.

Есть различные стратегии для слияния, рекурсивной является та, что вы зачастую будете видеть в Git, и Git выясняет, как сделать слияние двух бранчей. Если сейчас вы посмотрите на логи для мастер-бранча, что у нас есть новый коммит, Merge branch shorten_title, который идет после данного коммита, и это коммит, который связывает эти два элемента. И, конечно, если мы посмотрим сюда, мы ожидаем увидеть contact.html. А если мы посмотрим на страницу index.html, то и тут увидим сокращенное название. Вы можете удивиться, ведь index.html в основном бранче был другим. На первый взгляд, может показаться, что между двумя бранчами возник конфликт, но это не так, потому что изменение в shorten_title было сделано после этого. Здесь был этот предок, поэтому Git мог видеть его, он мог сказать - о, я вижу, позже этот элемент был изменен. Это слепок, который работает с данным изменением.

Так что никакого конфликта не было, так же как не было конфликта и тогда, когда мы делали быстрое слияние. Надеюсь, теперь вы имеете представление о двух способах, которыми Git делает слияние, то есть быстрое или реальное слияние, и, действительно, полезно понимать, как все происходит. Однако иногда при слиянии возникают конфликты. Иногда возникают проблемы, которые Git сам не может решить, и для этого ему нужна ваша помощь. Данный аспект мы рассмотрим в следующих роликах.