[Перевод - recovery mode ] Введение в Git Merge и Git Rebase: зачем и когда их использовать

Часто у разработчиков возникает выбор между Merge (слияние) и Rebase (перемещение). В Гугле вы увидите разное мнение, многие советуют не использовать Rebase, так как это может вызвать серьезные проблемы. В статье я объясню, что такое слияние и перемещение, почему вы должны (или не должны) использовать их и как это сделать.

image

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

Некоторые считают, что вы всегда должны использовать Rebase, другие предпочитают Merge. В этом есть свои плюсы и минусы.

Git Merge


Слияние — обычная практика для разработчиков, использующих системы контроля версий. Независимо от того, созданы ли ветки для тестирования, исправления ошибок или по другим причинам, слияние фиксирует изменения в другом месте. Слияние принимает содержимое ветки источника и объединяет их с целевой веткой. В этом процессе изменяется только целевая ветка. История исходных веток остается неизменной.
image
Плюсы:

  • простота;
  • сохраняет полную историю и хронологический порядок;
  • поддерживает контекст ветки.


Минусы:

  • история коммитов может быть заполнена (загрязнена) множеством коммитов;
  • отладка с использованием git bisect может стать сложнее.


Как это сделать

Слейте ветку master в ветку feature, используя команды checkout и merge.

$ git checkout feature
$ git merge master
(or)
$ git merge master feature


Это создаст новый «Merge commit» в ветке feature, который содержит историю обеих веток.

Git Rebase


Rebase — еще один способ перенести изменения из одной ветки в другую. Rebase сжимает все изменения в один «патч». Затем он интегрирует патч в целевую ветку.

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

image

Плюсы:

  • Упрощает потенциально сложную историю
  • Упрощение манипуляций с единственным коммитом
  • Избежание слияния коммитов в занятых репозиториях и ветках
  • Очищает промежуточные коммиты, делая их одним коммитом, что полезно для DevOps команд


Минусы:

  • Сжатие фич до нескольких коммитов может скрыть контекст
  • Перемещение публичных репозиториев может быть опасным при работе в команде
  • Появляется больше работы
  • Для восстановления с удаленными ветками требуется принудительный пуш. Это приводит к обновлению всех веток, имеющих одно и то же имя, как локально, так и удаленно, и это ужасно.


Если вы сделаете перемещение неправильно, история изменится, а это может привести к серьезным проблемам, поэтому убедитесь в том, что делаете!

Как это сделать

Переместите ветку feature на главной ветке, используя следующие команды.

$ git checkout feature
$ git rebase master


Это перемещает всю ветку функции в главную ветку. История проекта изменяется, создаются новые коммиты для каждого коммита в основной ветке.

Интерактивное перемещение


Это позволяет изменять коммиты при их перемещении в новую ветку. Это лучше, чем автоматическое перемещение, поскольку обеспечивает полный контроль над историей коммитов. Как правило, используется для очистки истории до слияния ветки feature в master.

$ git checkout feature
$ git rebase -i master


Это откроет редактор, перечислив все коммиты, которые будут перемещены.

pick 22d6d7c Commit message#1
pick 44e8a9b Commit message#2
pick 79f1d2h Commit message#3


Это точно определяет, как будет выглядеть ветка после выполнения перемещения. Упорядочивая объекты, вы можете сделать историю такой, как захотите. Вы можете использовать команды fixup, squash, edit, и так далее.

image

Какой из них использовать?


Так что же лучше? Что рекомендуют эксперты?

Трудно принять единственно правильное решение о том, что лучше использовать, поскольку все команды разные. Всё зависит от потребностей и традиций внутри команды.

Принимайте решения на основании компетенции команды в Git. Для вас важна простота или перезаписывание истории, а может быть что-то другое?

Что рекомендую я?

По мере роста команды становится сложно управлять или отслеживать изменения в разработке, применяя слияние. Чтобы иметь чистую и понятную историю коммитов, разумно использовать Rebase.

Преимущества Rebase:

  • Вы разрабатываете локально: если вы не делились своей работой с кем-либо еще. На данный момент вы должны предпочесть перемещение слиянию, чтобы сохранить свою историю в порядке. Если у вас есть личная вилка репозитория, которая не используется совместно с другими разработчиками, вы можете делать rebase даже после того, как переместились в свою ветку.
  • Ваш код готов к ревью: вы создали пулл реквест. Другие анализируют вашу работу и потенциально стягивают ее к своей вилке для локального ревью. На данный момент вы не должны перемещать свою работу. Вы должны создать коммит «переделать» и обновить ветку. Это помогает отслеживать запросы на пулл реквест и предотвращает случайную поломку истории.
  • Ревью сделано и готово к интеграции в целевую ветку. Поздравляем! Вы собираетесь удалить свою ветку feature. Учитывая, что с этого момента другие разработчики не будут fetch-merging эти изменения, это ваш шанс изменить вашу историю. На этом этапе вы можете переписать историю и сбросить оригинальные коммиты, и эти надоедливые «переделки» и «слияние» сливаются в небольшой набор целенаправленных коммитов. Создание явного слияния для этих коммитов является необязательным, но имеет значение. Он записывает, когда функция достигла master.


Теперь вы знаете хоть и незначительную, но разницу между Merge и Rebase. Уверен, вы примете правильное решение и будете использовать то, что подходит именно вам.

Не забывайте:

code = coffee + developer

© Habrahabr.ru