что такое git rebase

git rebase для начинающих

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

Итак git работает с комитами. Каждый комит — набор изменений. У каждого комита есть уникальный hash. Когда происходит слияние веток посредством merge:

то все комиты сохраняются — сохраняются комментарии комита, его hash + как правило добавляется еще один искусственный комит. При этом комиты могут чередоваться друг с другом. Это не всегда удобно. Допустим ваш комит решили откатить — выискивать в общем списке где ваш комит, а где не ваш не очень приятно. И вообще — в общей истории хочется видеть действительно важные изменения, а не «ой, я забыл поставить ;». Для того, чтобы несколько комитов склеивать в один можно использовать rebase. Хотя в интерфейсе GitHub есть кнопочка squash & commit — это когда вы создаете pull request (PR) из одной ветки в другую (как правило из вашей рабочей ветки в основную) и после прохождения всех формальностей можно нажать squash & commit, обновить комментарий и ваши изменения появятся в основной ветке как один комит.

Из плюсов — можно весь код, все изменения посмотреть в IDE. Иногда бывает удобнее, чем через web UI, который на GitHub.

Осторожно rebase может менять hash комита и приводить к конфликтам слияний, особенно если над одной веткой трудятся несколько человек.

Хочу написать о двух случаях использования rebase:

При этом все комментарии, которые были в fixup комитах потеряются и будет использоваться комментарий от первого комита. Если вам были дороги комментарии, то стоит использовать squash вместо fixup.

Вдогонку напишу что у меня получилось. Дано — 2 ветки — master и b1. В процессе работы мы сделали комиты:

Комиты в master и b1 были сделаны независимо. Написал в один список, чтобы был понятен порядок в котором все делалось. Вот список комитов в каждом бранче:

# git checkout master && git log
8dcef6c «+1»
b505f18 «master after b1.1»
2fbbe67 «Initial commit»

# git checkout b1 && git log
2d7d4ea «b1.2»
85eac43 «b1.1»
2fbbe67 «Initial commit»

Делаем git merge master в b1

# git checkout b1 && git merge master && git log
5383781 «Merge branch ‘master’ into b1»
8dcef6c «+1»
2d7d4ea «b1.2»
b505f18 «master after b1.1»
85eac43 «b1.1»
2fbbe67 «Initial commit»

Добавился новый синтетический комит

Теперь делаем rebase

# git checkout b1 && git rebase master && git log
7f18e47 «b1.2»
6fb80cb «b1.1»
8dcef6c «+1»
b505f18 «master after b1.1»
2fbbe67 «Initial commit»

Обратите внимание — наши локальные комиты встали в конец списка, номера комитов изменились, синтетический комит исчез.

Ну и напоследок склеиваем наши комиты в один

pick 6fb80cb b1.1
pick 7f18e47 b1.2

Файл стало после нашего редактирования

pick 6fb80cb b1.1
fixup 7f18e47 b1.2

# git checkout b1 && git log
9062cd7 «b1.1»
8dcef6c «+1»
b505f18 «master after b1.1»
2fbbe67 «Initial commit»

Такие дела

Источник

Простое объяснение Git Rebase

Перевод статьи «Git Rebase Explained Simply».

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

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

Забавно, но rebase это одна из нескольких команд git, которыми я лично пользуюсь практически ежедневно. По большому счету, я делаю rebase по крайней мере единожды для каждого пул-реквеста на GitHub.

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

Использование команды git rebase перестанет быть чем-то сложным или пугающим, как только вы поймете, как она работает и чем полезна.

Итак, представьте, что у вас есть две ветки.

Первая выглядит так:

Если присмотреться, можно заметить, что вплоть до 13363dd3 основа веток (base) одинакова, а дальше они расходятся.

Первая ветка, которую мы будем считать нашей рабочей веткой, содержит три коммита, которых нет во второй ветке.

Вторая ветка (в нашем примере — master) содержит восемь коммитов, не имеющихся в нашей рабочей ветке.

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

Допустим, вы занимаетесь разработкой какой-нибудь отдельной фичи и делаете это в отдельной ветке. Если эта ваша ветка просуществует хотя бы несколько дней, скорее всего за это время ветка master успеет измениться (т. е., еще до того, как вы вольете свою ветку обратно в master).

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

Если мы «уравняем» нашу рабочую ветку с веткой master в ее теперешнем состоянии, а затем поместим три своих коммита сверху, мы получим следующую историю:

Таким образом пул-реквест в master будет куда чище, кроме того, это поможет избежать конфликтов слияния.

К счастью, все это возможно благодаря перебазированию ветки!

Давайте обратим внимание на само название команды: Rebase. Что оно означает?

Применяя эту команду, мы заменяем основу (базу) нашей рабочей ветки на на ветку master. Т.е., мы «перебазируем» («re-base») рабочую ветку, меняем ее основу.

Использование git rebase

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

Давайте теперь познакомимся поближе с самой командой.

Предположим, у нас есть working-branch (рабочая ветка), проверенная на нашей локальной машине. В таком случае rebase выглядит просто:

Вы увидите в консоли некий output:

Как мы видим, git заново «проигрывает» нашу работу, как своего рода музыкальную запись, сверху ветки master.

Если вывести лог истории git, вы увидите, что наши изменения записаны поверх ветки master.

То есть, мы «перебазировали» нашу ветку, заменив ее основу на ветку master.

Если использование rebase все еще пугает вас, попробуйте делать копию своей рабочей ветки, прежде чем запускать команду rebase — просто на всякий случай!

Источник

Перебазирование

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

Простейшее перебазирование

Если вы вернётесь к более раннему примеру из Основы слияния, вы увидите, что разделили свою работу и сделали коммиты в две разные ветки.

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

В данном примере переключимся на ветку experiment и перебазируем её относительно ветки master следующим образом:

Это работает следующим образом: берётся общий родительский снимок двух веток (текущей, и той, поверх которой вы выполняете перебазирование), определяется дельта каждого коммита текущей ветки и сохраняется во временный файл, текущая ветка устанавливается на последний коммит ветки, поверх которой вы выполняете перебазирование, а затем по очереди применяются дельты из временных файлов.

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

После этого вы можете переключиться обратно на ветку master и выполнить слияние перемоткой.

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

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

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

Более интересные перемещения

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

Теперь вы можете выполнить перемотку (fast-forward) для ветки master (см Перемотка ветки master для добавления изменений из ветки client ):

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

После чего вы сможете выполнить перемотку основной ветки ( master ):

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

Опасности перемещения

Но даже перебазирование, при всех своих достоинствах, не лишено недостатков, которые можно выразить одной строчкой:

Не перемещайте коммиты, уже отправленные в публичный репозиторий

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

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

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

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

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

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

Если вы посмотрите git log в этот момент, вы увидите два коммита с одинаковыми авторами, датой и сообщением, что может сбить с толку. Помимо этого, если вы отправите свою историю на удалённый сервер в таком состоянии, вы вернёте все эти перебазированные коммиты на сервер, что ещё больше всех запутает. Логично предположить, что разработчик не хочет, чтобы C4 и C6 были в истории, и именно поэтому она перебазируется в первую очередь.

Меняя базу, меняй основание

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

Оказывается, что помимо контрольной суммы коммита SHA-1, Git также вычисляет контрольную сумму отдельно для патча, входящего в этот коммит. Это контрольная сумма называется «patch-id».

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

Определять, какая работа уникальна для вашей ветки (C2, C3, C4, C6, C7)

Определять, какие коммиты не были коммитами слияния (C2, C3, C4)

Определять, что не было перезаписано в основной ветке (только C2 и C3, поскольку C4 — это тот же патч, что и C4′)

Применять эти коммиты к ветке teamone/master

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

Это возможно, если C4 и C4′ фактически являются одним и тем же патчем, который был сделан вашим коллегой. В противном случае rebase не сможет определить дубликат и создаст ещё один патч, подобный C4 (который с большой вероятностью не удастся применить чисто, поскольку в нём уже присутствуют некоторые изменения).

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

Перемещение vs. Слияние

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

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

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

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

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

Источник

Руководство по Git. Часть №2: золотое правило и другие основы rebase

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

Это вторая и третья части гайда по Git из блога Pierre de Wulf в переводе команды Mail.ru Cloud Solutions. Первую часть можно почитать тут.

Суть rebase

Как именно происходит rebase:

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

Можно сказать, что rebase — это открепить ветку (branch), которую вы хотите переместить, и подключить ее к другой ветке. Такое определение соответствует действительности, но попробуем заглянуть чуть глубже. Если вы посмотрите документацию, вот что там написано относительно rebase: «Применить коммиты к другой ветке (Reapply commits on top of another base tip)».

Главное слово здесь — применить, потому что rebase — это не просто копипаст ветки в другую ветку. Rebase последовательно берет все коммиты из выбранной ветки и заново применяет их к новой ветке.

Такое поведение приводит к двум моментам:

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

Как видите, ветка feature содержит абсолютно новые коммиты. Как было сказано ранее, тот же самый набор изменений, но абсолютно новые объекты с точки зрения Git.

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

Теперь давайте обсудим «Золотое правило».

Золотое правило rebase

Золотое правило rebase звучит так — «НИКОГДА не выполняйте rebase расшаренной ветки!». Под расшаренной веткой понимается ветка, которая существует в сетевом репозитории и с которой могут работать другие люди, кроме вас.

Часто это правило применяют без должного понимания, поэтому разберем, почему оно появилось, тем более что это поможет лучше понять работу Git.

Давайте рассмотрим ситуацию, когда разработчик нарушает золотое правило, и что происходит в этом случае.

Предположим, Боб и Анна вместе работают над проектом. Ниже представлено, как выглядят репозитории Боба и Анны и исходный репозиторий на GitHub:

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

У всех пользователей репозитории синхронизируются с GitHub.

Теперь Боб, нарушая золотое правило, выполняет rebase, и в это же время Анна, работая в ветке feature, создает новый коммит:

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

Вы видите, что произойдет?

Боб пытается выполнить пуш коммита, ему приходит отказ примерно такого содержания:

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

Выполнение Git не было успешным, потому что Git не знает, как объединить feature ветку Боба с feature веткой GitHub.

Единственным решением, позволяющим Бобу выполнить push, станет использование ключа force, который говорит GitHub-репозиторию удалить у себя ветку feature и принять за эту ветку ту, которая пушится Бобом. После этого мы получим следующую ситуацию:

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

Теперь Анна хочет запушить свои изменения, и вот что будет:

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

Это нормально, Git сказал Анне, что у нее нет синхронизированной версии ветки feature, то есть ее версия ветки и версия ветки в GitHub — разные. Анна должна выполнить pull. Точно таким же образом, как Git сливает локальную ветку с веткой в репозитории, когда вы выполняете push, Git пытается слить ветку в репозитории с локальной веткой, когда вы выполняете pull.

Перед выполнением pull коммиты в локальной и GitHub-ветках выглядят так:

Когда вы выполняете pull, Git выполняет слияние для устранения разности репозиториев. И вот, к чему это приводит:

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

Коммит M — это коммит слияния (merge commit). Наконец, ветки feature Анны и GitHub полностью объединены. Анна вздохнула с облегчением, все конфликты устранены, она может выполнить push.

Боб выполняет pull, теперь все синхронизированы:

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

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

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

Также учтите, что появляются дубликаты коммитов в сетевом репозитории. В нашем случае — D и D’, содержащие одни и те же данные. По сути, количество дублированных коммитов может быть таким же большим, как и количество коммитов в вашей rebased ветке.

Если вы все еще не убеждены, давайте представим Эмму — третью разработчицу. Она работает в ветке feature перед тем, как Боб совершает свою ошибку, и в настоящий момент хочет выполнить push. Предположим, что к моменту ее push наш маленький предыдущий сценарий уже завершился. Вот что выйдет:

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

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

Красота pull rebase

Как вы видели выше, проблем Анны можно было избежать, если бы она использовала pull rebase. Рассмотрим этот вопрос подробнее.

Допустим, Боб работает в ветке, отходящей от мастера, тогда его история может выглядеть вот так:

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

Боб решает, что настало время выполнить pull, что, как вы уже поняли, приведет к некоторым неясностям. Поскольку репозиторий Боба отходил от GitHub, Git спросит делать ли объединение, и результат будет таким:

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

Это решение подходит и работает нормально, однако, вам может быть полезно знать, что есть другие варианты решения проблемы. Одним из них является pull-rebase.

Когда вы делаете pull-rebase, Git пытается выяснить, какие коммиты есть только в вашей ветке, а какие — в сетевом репозитории. Затем Git объединяет коммиты из сетевого репозитория с самым свежим коммитом, присутствующим и в локальном, и в сетевом репозитории. После чего выполняет rebase ваших локальных коммитов в конец ветки.

Звучит сложно, поэтому проиллюстрируем:

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

Как вы помните, при rebase Git применяет коммиты один за одним, то есть в данном случаем применяет в конец ветки master коммит E, потом F. Получился rebase сам в себя. Выглядит неплохо, но возникает вопрос — зачем так делать?

По моему мнению, самая большая проблема с объединением веток в том, что загрязняется история коммитов. Поэтому pull-rebase — более элегантное решение. Я бы даже пошел дальше и сказал, что когда нужно скачать последние изменения в вашу ветку, вы всегда должны использовать pull-rebase. Но нужно помнить: поскольку rebase применяет все коммиты по очереди, то когда вы делаете rebase 20 коммитов, вам, возможно, придется решать один за другим 20 конфликтов.

Как правило, можно использовать следующий подход: одно большое изменение, сделанное давно — merge, два маленьких изменения, сделанных недавно — pull-rebase.

Сила rebase onto

Предположим, история ваших коммитов выглядит так:

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

Итак, вы хотите выполнить rebase ветки feature 2 в ветку master. Если вы выполните обычный rebase в ветку master, получите это:

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

Нелогично выглядит то, что коммит D существует в обоих ветках: в feature 1 и feature 2. Если вы переместите ветку feature 1 в конец ветки мастер, получится, что коммит D будет применен два раза.

Предположим, что вам нужно получить другой результат:

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

Для реализации подобного сценария как раз и предназначен git rebase onto.

Сначала прочтем документацию:

Нас интересует вот это:

С помощью этой опции указывается, в какой точке создавать новые коммиты.

Если эта опция не указана, то стартовой точкой станет upstream.

Для понимания приведу еще один рисунок:

То есть ветка master — это newbase, а ветка feature 1 — upstream.

Источник

Git Rebase: руководство по использованию

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

Теория

Итак, освежим теоретические знания о том, что же такое rebase. Для начала вкратце — у вас есть две ветки — master и feature, обе локальные, feature была создана от master в состоянии A и содержит в себе коммиты C, D и E. В ветку master после отделения от нее ветки feature был сделан 1 коммит B.

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

После применения операции rebase master в ветке feature, дерево коммитов будет иметь вид:

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

Обратите внимание, что коммиты C’, D’ и E’ — не равны C, D и E, они имеют другие хеши, но изменения (дельты), которые они в себе несут, в идеале точно такие же. Отличие в коммитах обусловлено тем, что они имеют другую базу (в первом случае — A, во втором — B), отличия в дельтах, если они есть, обусловлены разрешением конфликтных ситуаций, возникших при rebase. Об этом чуть подробнее далее.

Такое состояние имеет одно важное преимущество перед первым, при слиянии ветки feature в master ветка может быть объединена по fast-forward, что исключает возникновение конфликтов при выполнении этой операции, кроме того, код в ветке feature более актуален, так как учитывает изменения сделанные в ветке master в коммите B.

Процесс rebase-а детально

Давайте теперь разберемся с механикой этого процесса, как именно дерево 1 превратилось в дерево 2?

Напомню, перед rebase вы находтесь в ветке feature, то есть ваш HEAD смотрит на указатель feature, который в свою очередь смотрит на коммит E. Идентификатор ветки master вы передаете в команду как аргумент:

Для начала git находит базовый коммит — общий родитель этих двух состояний. В данном случае это коммит A. Далее двигаясь в направлении вашего текущего HEAD git вычисляет разницу для каждой пары коммитов, на первом шаге между A и С, назовем ее ΔAC. Эта дельта применяется к текущему состоянию ветки master. Если при этом не возникает конфликтное состояние, создается коммит C’, таким образом C’ = B + ΔAC. Ветки master и feature при этом не смещаются, однако, HEAD перемещается на новый коммит (C’), приводя ваш репозитарий состояние «отделеной головы» (detached HEAD).

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

Успешно создав коммит C’, git переходит к переносу следующих изменений — ΔCD. Предположим, что при наложении этих изменний на коммит C’ возник конфликт. Процесс rebase останавливается (именно в этот момент, набрав git status вы можете обнаружить, что находитесь в состоянии detached HEAD). Изменения, внесенные ΔCD находятся в вашей рабочей копии и (кроме конфликтных) подготовлены к коммиту (пунктиром обозначена stage-зона):

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

Далее вы можете предпринять следующие шаги:

1. Отменить процесс rebase набрав в консоли

При этом маркер HEAD, будет перенесен обратно на ветку feature, а уже добавленные коммиты повиснут в воздухе (на них не будет указывать ни один указатель) и будут вскоре удалены.

При этом, если все конфликты действительно разрешены, будет создан коммит D’ и rebase перейдет к следующему, в данном примере последнему шагу.

После применения изменений ΔDE будет создан последний коммит E’, указатель ветки feature будет установлен на коммит E’, а HEAD станет показывать на ветку feature — теперь, вы находитесь в состоянии на втором рисунке, rebase окончен. Старые коммиты C, D и E вам больше не нужны.

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

При этом коммиты, созданные в процессе rebase-а, будут содержать данные как об оригинальном авторе и дате изменений (Author), так и о пользователе, сделавшем rebase (Commiter):

С небес на землю — rebase в реальных условиях

На самом деле обычно вы работаете не с двумя ветками, а с четырьмя в самом простом случае: master, origin/master, feature и origin/feature. При этом rebase возможен как между веткой и ее origin-ом, например feature и origin/feature, так и между локальными ветками feature и master.

Rebase ветки с origin-ом

Если вы хотите начать работать с rebase, то лучше всего начать с ребейза своих изменений в ветке относительно ее копии в удаленном репозитарии. Дело в том, что когда вы добавляете коммит, и в удаленном репозитарии добавляется коммит, для объединения изменений по-умолчанию используется merge. Выглядит это примерно так:

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

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

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

Как поделиться веткой, к которой применен rebase, с коллегой

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

Тут все просто, наберите в консоли команду:

Force-режим просто копирует отсутствующие родительские коммиты ветки feature на origin и насильно устанавливает указатель ветки на тот же коммит, что и ваш локальный.

Будьте внимательны! Если вы забудете указать идентификатор ветки, то force-push будет выполнен для всех локальных веток, имеющих удаленный оригинал. При этом нужно понимать, что некоторые локальные ветки могут быть в неактуальном состоянии. То есть измененения, которые вы не успели затянуть будут удалены в origin-е. Конечно, сами коммиты не будут удалены — сбросятся только указатели ветки. Эта ситуация поправима — достаточно для каждой ветки найти человека, который последним пушил изменения в нее или уже успел их забрать. Он может сделать обычный push, вновь передав их на origin. Но вся эта морока вам ни к чему, так что лучше просто будьте внимательны.

Реинтеграция тематической ветки в master

Мы рассмотрели все необходимые операции для работы с ветками в стиле rebase. Осталось только переключиться в ветку master и сделать git merge feature. Ветка, подготовленная rebase-ом вольется в master по fast-forward, то есть указатель будет просто перемещен вперед.

что такое git rebase. Смотреть фото что такое git rebase. Смотреть картинку что такое git rebase. Картинка про что такое git rebase. Фото что такое git rebase

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

Заключение

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

В данной статье сделано одно допущение. Все это верно при простой модели ветвления — есть одна главная ветка master и несколько тематических, которые создаются от нее. Когда от тематической ветки создается другая тематическая ветка, есть свои нюансы при rebase-е первичной и вторичной ветки. О них можно прочитать в том самом официальном руководстве.

Иногда споры, что же лучше merge или rebase доходят до холивара. От себя могу сказать, что в конечном счете выбор за вами, однако этот выбор не может быть продиктован уровнем владения тем или иным инструментом. Обоснованный выбор можно сделать, только когда для вас не составит труда работать и в том и в другом стиле. Я не агитирую за повсеместное использование rebase-а, а просто объясняю как им пользоваться. Надеюсь, это статья поможет вам снять вопросы, связанные с механизмом работы rebase и его применением в ежедневной работе.

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

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *