Skip to content
aplb edited this page Mar 27, 2014 · 34 revisions

МЕХАНИКА REBASE.

Итак, рассмотрим следующую историю. (Коммиты сгенерированы рандомно).

(Тестовый репо на https://github.com/aplb/rebase-mechanics.git)

┏ 56b34f8 (46 seconds ago) aplb A random change of 14253 to master1.txt
┣ ded8f1a (46 seconds ago) aplb A random change of 5174 to master2.txt
┣━┓
┃ ┣ c627aa2 (46 seconds ago) aplb A random change of 29717 to master3.txt
┃ ┗━[master]──a0e75cc (46 seconds ago) aplb A random change of 23710 to master4.txt
┣ 6653efe (3 seconds ago) aplb A random change of 9225 to feat1.txt
┣ f90c50d (3 seconds ago) aplb A random change of 14433 to feat2.txt
┗━[HEAD]──[feat]──88a1762 (3 seconds ago) aplb A random change of 3753 to feat3.txt

От ветки master в определенный момент пошла линия разработки feat, в ней были сделаны 3 коммита. Чтобы поддерживать историю линейной, стоит задача: поместить эти коммиты на верхушку master, при этом коммиты 1 и 2 можно уплотнить в один. С этим поможет справиться

git rebase -i master

pick 6653efe A random change of 9225 to feat1.txt
pick f90c50d A random change of 14433 to feat2.txt
pick 88a1762 A random change of 3753 to feat3.txt

На второй строке редактора 'pick f90c50d' заменяем pick на squash (или s), чтобы уплотнить коммит f90c50d с его предшественником 6653efe в один. Смотрим историю.

┏ 56b34f8 (5 minutes ago) aplb A random change of 14253 to master1.txt
┣ ded8f1a (5 minutes ago) aplb A random change of 5174 to master2.txt
┣ c627aa2 (5 minutes ago) aplb A random change of 29717 to master3.txt
┣━[master]──a0e75cc (5 minutes ago) aplb A random change of 23710 to master4.txt
┣ 8d00dbf (4 minutes ago) aplb This is a combination of 2 commits: feat1 and feat2
┗━[HEAD]──[feat]──766cfcd (4 minutes ago) aplb A random change of 3753 to feat3.txt

Получилось. История изменений линейна, из двух коммитов сплющен один. Можно безболезненно выполнить fast-forward merge на master-е. Стоит все же напомнить, что перемещенные коммиты не являются теми же самыми. У них другой sha1-hash. Родителем нашего squashed-коммита 8d00dbf выступает коммит a0e75cc, на который указывает ветка master.

Это было вступление. А теперь вернемся к изначальному состоянию истории и попробуем выполнить то же самое с помощью более простых команд.

Чтобы повторить 'git rebase -i master', для начала перейдем на ветку master.

git checkout master

Надо понимать, что разницей между двумя коммитами является дельта. Выполняя rebase, Git вычисляет дельту между коммитами (ветки feat) и последовательно применяет их (дельты) на ветке, на которую выполняется перемещение (в данном случае master). Также я создам специально для rebase ветку

git checkout -b tmp-rebase master
git diff ded8f1a 6653efe | git apply
  1. Для начала определим разницу при переходе из ded8f1a в коммит 6653efe, затем по цепочке команд применим дельту к working tree, что позволяет не использовать временный файл. Команда git-status показывает, что в дереве проекта появились изменения. С помощью git-add и git commit создадим новый коммит. И хотя, показывая git rebase -i, я делал squash для 1 и 2 коммитов ветки feat, в текущем примере я выполню squash для 2 и 3.

  2. Далее можно последовательно получать diff между коммитами, применяя его

git diff 6653efe f90c50d

и

git diff f90c50d 88a1762

Но поскольку это простой учебный пример, можно получить и применить два diff-а сразу.

git diff 6653efe 88a1762 | git apply

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

Вот практически и всё. Некоторую информацию о полученных изменениях можно извлечь из вывода

git log -p -2

В завершение я переименую временную ветку в feat, тем самым удалив старую.

git branch -M feat

История изменений теперь выглядит так:

┏ 56b34f8 (63 minutes ago) aplb A random change of 14253 to master1.txt
┣ ded8f1a (63 minutes ago) aplb A random change of 5174 to master2.txt
┣ c627aa2 (63 minutes ago) aplb A random change of 29717 to master3.txt
┣━[master]──a0e75cc (63 minutes ago) aplb A random change of 23710 to master4.txt
┣ ebca023 (6 minutes ago) aplb Rebased commit-1
┗━[HEAD]──[feat]──ea00eb6 (65 seconds ago) aplb Rebased commits 2 and 3

что похоже на результат, полученный во вводной части. Нет ничего легче перемотки fast-forward.

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

Clone this wiki locally