Поиск по сайту:

Что такое Git Rebase и чем он отличается от слияния?


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

Что происходит с ребазингом?

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

Git хранит ваш код в виде серии правок. Вы можете думать об этом как о цепочке, работающей в обратном направлении. Каждое редактирование или «фиксация» ссылается на идентификатор предыдущей фиксации и включает в себя то, что изменилось по сравнению с предыдущей фиксацией. Эта цепочка хранится только на вашем компьютере; ваш клиент Git не взаимодействует с другими клиентами Git, если только он не выполняет fetch или push (pull на самом деле просто fetch + объединить с вашей локальной веткой), и даже в этом случае он общается только с общим удаленным репозиторием.

Филиалы более сложные. При работе с ветками Git сохраняет только одну вещь: идентификатор коммита в конце ветки. Таким образом, вы можете думать о них как о головке воспроизведения на проигрывателе; вы помещаете головку ветки в определенную позицию, и она возвращается обратно по цепочке, «проигрывая» ваш код и получая окончательную версию. Всякий раз, когда вы совершаете коммит, ваш локальный клиент git автоматически перемещает указатель воспроизведения вперед к новому коммиту.

Если вы хотите объединить функцию с мастером, вы должны запустить:

git checkout master
git merge feature

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

Этот метод слияния кода представляет три проблемы:

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

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

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

Чтобы выполнить этот процесс из командной строки, вы должны запустить:

git checkout feature
git pull
git rebase master

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

На данный момент код в ветке функций более актуален, что является единственной реальной функцией git rebase. Перебазирование не объединяет ветки, поскольку оно не создает коммитов слияния и не перемещает точку воспроизведения мастера.

Если вы хотите выполнить слияние после перебазирования, вы должны запустить:

git checkout master
git merge feature

Это будет выглядеть так, если головка воспроизведения мастера заменит головку воспроизведения функции:

Таким образом, перебазирование не решает проблему слияния, так как вам все равно придется сливать в конце, чтобы обновить основную ветку. Фактическая команда merge в конце должна пройти без сучка и задоринки, поскольку процесс перемещения требует от вас «объединения» изменений, что по-прежнему может вызывать конфликты. И если вы все еще хотите продолжить работу над своей веткой, вам все равно нужно «слить» изменения.

Не перебазировать общие ветки

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

Ветка feature2 вашего коллеги теперь ссылается на старую цепочку коммитов. Ваш Git-клиент не может знать об этом, поскольку ветка feature2 хранится на компьютере вашего коллеги. У них также нет возможности узнать, что вы перебазировались, пока вы не нажмете свои изменения.

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

Суть в том, что не выполняйте перебазирование, если вы не работаете локально.

Когда перебазирование лучше, чем слияние?

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

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

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

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