Разбираемся с git rebase

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

Перейду сразу к сути. Я использую git rebase в двух случаях:
  • Чтобы сделать устаревшую ветку актуальной.
  • Чтобы изменить серию неслитых коммитов.



Рассмотрим каждый случай подробнее.

Делаем ветку актуальной

Некоторые считают, что git rebase — это команда, которая отвечает в Git за магию. Но если разложить по полочкам, как она работает, мы поймём, в чём тут колдовство.

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

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



Когда мы смотрим на дерево целиком, мы видим устаревшую ветку красного цвета, которая отходит от master. При внимательном изучении мы замечаем, что ветка устарела, потому что в ней нет последних коммитов из master (на рисунке синие).

Если запустить git rebase, команда сначала отматывает обе ветки назад до момента, когда их истории коммитов совпадали (участки серого цвета). Потом git rebase в режиме fast-forward перемещается через все коммиты master и применяет их к устаревшей ветке. И наконец, команда заново воспроизводит коммиты устаревшей ветки.
Получившееся дерево выглядит так, будто вы создали новую ветку от master и сделали коммиты. Таким образом, с помощью git rebase проще сделать аккуратное слияние.

Меняем серию коммитов

Мне нравится использовать git rebase, чтобы менять сразу несколько коммитов. Бывает, я на скорую руку делаю коммиты, пока работаю над веткой feature, а потом мне нужно подчистить её перед слиянием. Для этого приходится или сжимать коммиты (squash), или переписывать сообщения к ним.

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

Результат похож на то, что дает команда git log --oneline. Однако тут к каждому коммиту присоединена команда. В комментариях содержится описание каждой команды.



p, pick – использовать коммит
r, reword – использовать коммит, редактировать сообщение коммита
e, edit – использовать коммит, предварительно внеся правки
s, squash – использовать коммит, слить с предыдущим коммитов
f, fixup – то же, что и squash, не учитывать лог сообщений коммита
x, exec – выполнить команду (оставшаяся часть строки) с помощью shell
d, drop – убрать коммит

Обычно я использую префикс r, чтобы переформулировать сообщение коммита с помощью reword, и f, чтобы склеить коммит командой fixup, не меняя сообщение коммита. Несмотря на то, что многие склеивают коммиты при помощи squash, я использую fixup намного чаще. Дело в том, что squash на один шаг дольше, потому что требует редактировать сообщения коммитов.

После сохранения git rebase -i заново воспроизводит все коммиты и применяет заданные вами команды.

Пара предостережений:

  • Могут случаться конфликты.
  • Заново воспроизведённые коммиты не равны изначальным — они получают новый хэш SHA.

Если вы делаете небольшие связанные коммиты (см. статью Когда нужно делать коммит), вам будет легко разрешить любой конфликт.

И помните, что git rebase всегда меняет хэш заново воспроизведенных коммитов. То есть если вы поделились коммитами с кем-то ещё или слили их с другой веткой, Git будет определять их как новые.

Автор: Jason McCreary

Нет комментариев