# Владеешь merge  -  освой и rebase

Независимо от используемых в проекте стратегий ветвления, приходится регулярно интегрировать изменения из одной ветки в другую. В `git` это можно сделать двумя основными способами: `merge` (слияние) и `rebase` (перебазирование).

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

Сначала с помощью анимационных средств разберем каждую операцию по отдельности, а на заключительном этапе проведем параллельное сравнение. Если вам уже знакомы принципы работы этих действий, то сразу переходите к сравнительным характеристикам.&#x20;

Согласно официальному руководству Git `rebase` *“повторно применяет коммиты поверх другой базовой ветки”*, тогда как `merge` *“объединяет две или более историй разработки”.* Иначе говоря,основное отличие между ними в том, что слияние *сохраняет историю в первозданном виде, а* перебазирование *ее перезаписывает*. Прежде чем переходить к более подробному осмыслению принципов их внутренней работы, обратимся к примеру: ![](https://cdn-images-1.medium.com/max/533/0*7xzfJA__cDwTf0DT.png)Обзор истории коммитов с позиции Satoshi, в которой удаленный репозиторий “origin” для удобства обозначен как “о”. Обратите внимание, что в настоящий момент локальная ветка “master “ (C1) отстает от своего удаленного аналога “o/master” (C4).

Как видно из примера, разработчики Ada и Satoshi изначально создали 2 тематические ветки (`feature-1` и `feature-2`), происходящие из одного и того же коммита (`C1`) на ветке `master`. Затем Ada завершила работу с `feature-1`, осуществив ее слияние с `master` (создав коммит слияния `C4`). Теперь у Satoshi есть два способа интегрировать изменения Ada в свою ветку `feature-2` —  слияние или перебазирование.&#x20;

**Слияние**&#x20;

Начнем с самого распространенного рабочего процесса интеграции изменений: слияния. Перед объединением изменений Ada с `feature-2` Satoshi должен сначала обновить свой локальный указатель на `master` ветку, поскольку в данный момент она устарела. Как только `master` и `o/master` синхронизируются, Satoshi сможет включить все изменения в свою тематическую ветку.

Процесс слияния:&#x20;

После всех изменений в `feature-2` Satoshi может продолжить разработку ветки и на заключительном этапе объединить ее с `master`.&#x20;

Ниже представлен окончательный результат слияния. Как видно, история разработки сохраняет все свои этапы  —  добавляется только коммит слияния `C7`.![](https://cdn-images-1.medium.com/max/533/0*K8_x-EgGnDt8Q6QP.png)

#### Перебазирование  <a href="#h--1" id="h--1"></a>

Имея в виду процесс слияния, рассмотрим тот же пример, но уже с точки зрения перебазирования. Так же как и в предыдущем случае, перед интеграцией изменений Satoshi должен убедиться, что его локальная и удаленная ветки `master` синхронизированы. Но затем вместо обычного слияния, сохраняющего историю в ее поэтапном виде, он может интегрировать все изменения с помощью операции перебазирования, таким образом перезаписывая истори&#x44E;*.*

Выполняя перебазирование `feature-2` относительно `master`, Git вернется назад и повторно выполнит коммиты `C5` и `C6` один за другим прямо поверх `C4`, создавая впечатление, что `feature-2` изначально была ответвлением конечных изменений Ada.&#x20;

Процесс перебазирования:&#x20;

После повторной интеграции всех изменений Satoshi может продолжить работу над своей тематической веткой.&#x20;

Ниже представлен конечный результат перебазирования. Обратите внимание на повторное выполнение коммитов `C5` и `C6` поверх `C4`, повлекшее за собой перезаписывание истории разработки и полное удаление старых коммитов! ![](https://cdn-images-1.medium.com/max/533/0*ktyEOUW-T2uQ9Y4V.png)Как видно, хеши C5 и C6 изменились. Обусловлено это тем, что фактически они являются вновь созданными коммитами (хотя их содержание все еще может быть идентичным)

Понимая главное отличие между слиянием и перебазированием, проанализируем конечные результаты этих операций.&#x20;

#### Сравнение слияния и перебазирования  <a href="#h--2" id="h--2"></a>

![](https://cdn-images-1.medium.com/max/533/0*E3VWx7JmBeLeodUB.png)Начальное состояние и параллельное сравнение конечных состояний слияния и перебазирования

Как видим, после слияния две ветки объединились в новом коммите (`C7`), придавая нелинейной истории ромбовидную форму и *сохраняя ее в неизменном виде*. В отличие от этой операции перебазирование привело не к созданию коммита слияния, а к возврату и повторному применению коммитов `C5` и `C6` поверх `C4`, обеспечивая линейность истории. Более детальное изучение этих коммитов позволяет выявить изменения их хешей, подтверждающее факт *перезаписи истории* в результате перебазирования.&#x20;

***Примечание:** каждый раз перебазирование ветки будет сопровождаться созданием новых коммитов, даже если их содержимое останется одним и тем же. Таким образом, прежние коммиты будут в итоге полностью удалены из истории.*&#x20;

#### С большой силой приходит большая ответственность  <a href="#h--3" id="h--3"></a>

Итак, теперь мы знаем, что перебазирование перезаписывает историю, а слияние ее сохраняет. Но что это значит в более широком смысле? Какие возможности и потенциальные недочеты таят в себе две эти операции?&#x20;

#### Конфликты при интеграции изменений  <a href="#h--4" id="h--4"></a>

Допустим, попытка интегрировать изменения обернулась рядом неприятных конфликтов. Прибегнув к слиянию, вы бы решили их все за раз прямо в коммите `C7`. А вот в случае с перебазированием вам бы пришлось решать одни и те же конфликты в каждом коммите (`C5` и `C6`) по мере их повторного применения.&#x20;

Трудноразрешимые конфликты говорят о недостатке общения с коллегами ввиду очень длительной работы над одними и теми же файлами.&#x20;

#### Опубликованные ветки  <a href="#h--5" id="h--5"></a>

Еще одна потенциальная проблема связана с ситуацией, в которой ветка, подлежащая перебазированию, уже удаленно опубликована и положена в основу чьей-либо работы. Тогда такая перебазированная ветка может запутать и усложнить процесс для всех участников, поскольку Git укажет, что она одновременно и отстает, и опережает. В этом случае проблема решается путем извлечения изменений из удаленного репозитория с последующим внедрением в текущий, для чего служит флаг `--rebase` (`git pull --rebase`).

Кроме того, всякий раз при перебазировании уже опубликованной ветки, независимо от того, основывается ли на ней чья-либо работа, вам по прежнему необходимо *принудительно опубликовать* ее для внесения обновлений в удаленный сервер, тем самым полностью переписывая текущий указатель.&#x20;

#### Потеря данных (как преимущество)  <a href="#h--6" id="h--6"></a>

Поскольку слияние сохраняет историю, а перебазирование ее переписывает, то последняя операция может привести к потере данных. При повторном выполнении новых коммитов старые удаляются (после сборки мусора). Именно эта особенность повышает эффективность команды `rebase`, позволяющей очистить историю разработки, прежде чем сделать ее общедоступной. А с помощью интерактивного перебазирования можно удалять ненужные коммиты, сжимать изменения или просто обновлять сообщения коммитов.&#x20;

#### Главные правила перебазирования  <a href="#h--7" id="h--7"></a>

Во избежание связанных с перебазированием проблем рекомендуется придерживаться следующих правил:&#x20;

* Не перебазируйте ветку, опубликованную удаленно…
* …если только вы не уверены, что кроме вас с ней никто не работает (и что ее принудительная публикация не вызовет проблем).&#x20;
* Создайте резервную ветку, исходящую из конечной точки ветки, подлежащей перебазированию. Это позволит легко сравнить результат (по завершении) и при необходимости вернуться к состоянию, предшествующему перебазированию.&#x20;

#### Усложненные случаи перебазирования  <a href="#h--8" id="h--8"></a>

Существует множество усложненных операций перебазирования. К числу наиболее эффективных из них относится ранее упомянутый его *интерактивный вариант*, позволяющий определить способ повторного выполнения каждого коммита. &#x20;

Данный режим применяется для разделения, сжатия, перегруппировки и даже полного удаления коммитов, и этим его возможности не ограничиваются.&#x20;

#### Заключение <a href="#h--9" id="h--9"></a>

Многие разработчики предпочитают вместо `rebase` выполнять `merge`, поскольку они уверены, что так не потеряют результаты своей работы. В некотором смысле такой веский аргумент оправдывает отказ от неудобных в работе инструментов. А вот нежелание постичь все преимущества эффективных возможностей, будучи о них осведомленным, оправдать нельзя!&#x20;

Такой подход равносилен высказыванию: “Хоть у меня и отличная машина, но лучше я ограничусь первой передачей, ведь скоростная езда смертельно опасна”. А почему бы не научиться переключать передачи и безопасно передвигаться на высоких скоростях?!

Мой собственный опыт показал, что знание принципов перебазирования углубляет понимание Git, а также развивает вас как разработчика, особенно если речь идет об управлении исходным кодом.&#x20;

Как-то в самом начале моей карьеры разработчика я получил один из лучших советов от более опытного коллеги. Звучит он так: “Хватит стучать по клавишам в Source Tree, лучше научись использовать команды Git из терминала! Иначе ты не познаешь все возможности Git, и в перспективе не сможешь программировать автоматические конвейеры.”

С тех пор в качестве визуального средства для просмотра дерева истории я предпочитаю только [GitK](https://git-scm.com/docs/gitk), а все команды набираю в терминале. И вам рекомендую!&#x20;

Теперь, понимая разницу между слиянием и перебазированием, вы с большей уверенностью начнете применять обе операции.&#x20;

Ссылка:

<https://nuancesprog.ru/p/12275/><br>
