Тур по Git
История и отмена изменений / Урок 3.10

git rebase --onto — Продвинутый rebase

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

Форма с тремя аргументами

git rebase --onto <новая-база> <upstream> <ветка>

Это означает: взять коммиты из <ветка>, которых нет в <upstream>, и воспроизвести их поверх <новая-база>.

  • новая-база — куда вы хотите поместить коммиты
  • upstream — начальная точка (не включительно) коммитов, которые вы хотите переместить
  • ветка — ветка, верхушка которой содержит коммиты, которые вы хотите переместить

Сценарий 1: Перемещение ветки, основанной на неправильной ветке

Допустим, вы случайно создали feature-B от feature-A вместо main:

До:
A — B — C                  (main)
         \
          D — E             (feature-A)
               \
                F — G       (feature-B)

Вы хотите, чтобы feature-B (коммиты F и G) была основана на main вместо feature-A:

git rebase --onto main feature-A feature-B
После:
A — B — C                  (main)
        |\
        | D — E             (feature-A)
         \
          F' — G'           (feature-B)

Коммиты F' и G' воспроизведены непосредственно поверх main, как будто feature-A никогда не была в цепочке.

Сценарий 2: Удаление диапазона коммитов

Допустим, у вас есть ветка с несколькими коммитами в середине, которые вы хотите удалить:

До:
A — B — C — D — E — F      (feature)
        ^           ^
        |           |
     оставить     оставить
     (но удалить C, D)

Вы хотите удалить коммиты C и D, оставив только B, E и F:

git rebase --onto B D feature

Это означает: взять коммиты после D в ветке feature (то есть E и F) и воспроизвести их поверх B:

После:
A — B — E' — F'            (feature)

Форма с двумя аргументами

Вы также можете использовать --onto с двумя аргументами. Git подставит текущую ветку:

git checkout feature-B
git rebase --onto main feature-A

Это эквивалентно:

git rebase --onto main feature-A feature-B

Попробуйте!

Попрактикуйтесь в пересадке ветки с помощью git rebase --onto:

  1. Создайте начальный коммит в main:
    • echo "base" > file.txt && git add file.txt && git commit -m "Base commit"
  2. Создайте feature-A и добавьте два коммита:
    • git checkout -b feature-A
    • echo "feature-A work" > a.txt && git add a.txt && git commit -m "feature-A: first"
    • echo "more A work" >> a.txt && git add a.txt && git commit -m "feature-A: second"
  3. Создайте feature-B от feature-A и добавьте два коммита:
    • git checkout -b feature-B
    • echo "feature-B work" > b.txt && git add b.txt && git commit -m "feature-B: first"
    • echo "more B work" >> b.txt && git add b.txt && git commit -m "feature-B: second"
  4. Проверьте лог, чтобы увидеть всю цепочку:
    • git log --oneline --all --graph
  5. Теперь пересадите feature-B на main, убрав зависимость от feature-A:
    • git rebase --onto main feature-A feature-B
  6. Проверьте результат:
    • git log --oneline --all --graph
    • Коммиты feature-B теперь находятся непосредственно поверх main
    • ls — вы должны видеть file.txt и b.txt, но не a.txt

Ключевые моменты

  • git rebase --onto даёт точный контроль над тем, какие коммиты воспроизводятся и куда
  • Форма с тремя аргументами: git rebase --onto <новая-база> <upstream> <ветка>
  • Используйте его для пересадки ветки на другую базу или удаления диапазона коммитов
  • Как и обычный rebase, он переписывает историю — никогда не используйте его на общих/публичных ветках
  • Всегда проверяйте результат с помощью git log --oneline --all --graph после перебазирования
🎯

Цель

Используйте git rebase --onto для переноса ветки на другую базу

Terminal
$

No commits yet. Run `git init` and create your first commit.