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:
- Создайте начальный коммит в main:
echo "base" > file.txt && git add file.txt && git commit -m "Base commit"
- Создайте
feature-Aи добавьте два коммита:git checkout -b feature-Aecho "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"
- Создайте
feature-Bотfeature-Aи добавьте два коммита:git checkout -b feature-Becho "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"
- Проверьте лог, чтобы увидеть всю цепочку:
git log --oneline --all --graph
- Теперь пересадите
feature-Bнаmain, убрав зависимость отfeature-A:git rebase --onto main feature-A feature-B
- Проверьте результат:
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после перебазирования