Магия git rebase

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

Подготовка данных

Создадим каталог для нашего проекта:

Теперь откройте ваш текстовый редактор и с помощью него создайте простой текстовый файл “text.txt” в каталоге “git-rebase-magic” со следующим содержимым:

Закоммитим этот файл:

Создаём ветку “some-feature” и переключаемся на неё:

Внесите в текстовый файл следующие изменения и сохраните:

Закоммитте их:

Снова откройте текстовый файл и сделайте его вот таким:

Сделайте коммит:

Откройте текстовый файл и поправьте его, чтобы он выглядел вот так:

Коммит:

Одна ветка готова. Подготовим вторую ветку:

Поменяем содержимое нашего файла вот так:

Коммит:

Снова поменяем содержимое нашего файла:

Коммит:

Меняем файл в третий раз:

Коммит:

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

git rebase magic two branches

Немного магии git rebase

Находясь в ветке “second-feature” перенесём наши изменения из ветки “some-feature” в ветку “second-feature”:

Откроется текстовый редактор со следующим содержимым:

Допустим, что мы хотим перенести не все изменения, а только  изменение, в котором мы добавили фразу “added-cauldron”. Тогда оставим pick у него, а остальным проставим drop:

Обратите внимание, что в самом содержимом файла, который мы редактируем уже описаны все возможные команды. Сохраняем файл и выходим из редактора. Для nano это комбинация клавиш Ctrl+O, Enter, Ctrl+X.

Так как в ветке “some-feature” и “second-feature” были изменены одинаковые строки, то мы получим конфликт мержа:

Откройте текстовым редактором наш файл “text.txt” и исправьте конфликт. Исходный файл:

Исправленный (мы приняли изменения из обоих веток, можно было оставить только одну):

Коммитим изменения:

Продолжаем rebase:

Мы выбрали перенос (pick) только одного изменения, поэтому на этом наш rebase заканчивается:

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

Результат:

git rebase magic

В результате мы получили то, будто наша ветка “second-feature” отбранчевалась от коммита “added-striga” из ветки “some-feature”, и в ней был только один коммит “added-witcher and added-cauldron”. При желании мы могли бы перенести все коммиты.

Вывод: Команда git rebase -i some-feature сделала так, что наша текущая ветка будто бы изначально была сделана от текущей ветки “some-feature”, с последующим внесением тех изменений, который были в нашей ветке “second-feature”.

Если бы мы сейчас сделали pull request из ветки “second-feature” в ветку “some-feature”, то мы бы увидели только одно изменение “added-witcher and added-cauldron”.

При желании мы можем объединять коммиты. Например, сейчас мы находимся в ветке “second-feature”. Переключимся на ветку “some-feature” и смержим изменения туда:

Результат будет аналогичный тому, что мы сделали pull request и смержили изменения из “second-feature” в ветку “some-feature”.

git rebase magic after merge

Добавим немного магии. Нам вовсе нет необходимости иметь аж четыре коммита. Объединим их всех в один:

Цифра в “HEAD~4” означает какое количество коммитов в истории мы хотим поправить.

В открывшемся редакторе поправим текст вот так:

Сохраним файл. Нам предложат написать комментарий для объединённого коммита. Пусть это будет “squashed-commit”.

Теперь наш репозиторий будет выглядеть вот так:

Git rebase magic squashed

Как видим наша ветка “some-feature” теперь содержит только один коммит “squashed-commit”, который содержит все изменения, что были в этой ветке до этого. Ветка “second-feature” осталась нетронутой и содержит все коммиты, что были в ней до этого.

Для того чтобы запушить ветки с изменённой с помощью git rebase истории, вам потребуется воспользоваться git push —force или git push —force-with-lease.

Теперь вы знаете git rebase!

Магия git rebase: 4 комментария

  1. «В результате мы получили то, будто наша ветка “second-feature” отбранчевалась от коммита “added-striga” из ветки “some-feature”, и в ней был только один коммит “added-proof”.»

    Автор, что ты несёшь? В результате никакого следа от коммита «added-proof» не останется, потому что ребейзили коммит «added-witcher and added-cauldron»

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

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