Давайте пропустить --ontoна данный момент. upstreamи branchдовольно просты, и на самом деле имитируют checkoutи branch- второй аргумент является необязательным:
git branch <newbranch>
git branch <newbranch> <base>
git checkout -b <newbranch>
git checkout -b <newbranch> <base>
git rebase <upstream>
git rebase <upstream> <branch>
( За исключением, имена этих аргументов в rebase«вверх» и «ветви» не очень описательный IMO я обычно думаю о них , как peachoftree,. <start>И <end>, что , как я буду использовать их: git rebase <start> <end>)
Когда вторая ветвь опущена, результат почти такой же, как сначала проверить эту ветку, а затем сделать это так, как если бы вы не указали эту ветку. Исключением является то, branchчто не меняет вашу текущую ветку:
git checkout <base> && git branch <newbranch> && git checkout <previous_branch>
git checkout <base> && git checkout -b <newbranch>
git checkout <end> && git rebase <start>
Что касается понимания того, что rebaseпроисходит при вызове, я сначала начал думать об этом как об особом типе слияния. Это не совсем так, но помогло, когда впервые начал понимать ребаз. Взять пример с peachoftree:
A--B--F--G master
\
C--D--E feature
А git merge masterрезультаты в этом:
A--B--F-----G master
\ \
C--D--E--H feature
Хотя git rebase master(в то время как на ветке feature!) Приводит к этому:
A--B--F--G master
\
C'--D'--E' feature
В обоих случаях featureтеперь содержит код от обоих masterи feature. Если вы не featureвключены, второй аргумент может быть использован для переключения на него в качестве ярлыка: git rebase master featureбудет сделано то же самое, что и выше.
Теперь для спец --onto. Важно помнить, что по умолчанию используется значение, <start>если оно не указано. Так что выше, если бы я указал --ontoконкретно, это привело бы к тому же:
git rebase --onto master master
git rebase --onto master master feature
(Я не использую, --ontoне указывая <end>просто, потому что мысленно разобрать легче, даже если они оба одинаковые, если они уже включены feature.)
Чтобы понять, почему --ontoэто полезно, вот другой пример. Допустим, я был включен featureи заметил ошибку, которую я затем начал исправлять, но featureвместо нее произошел ответвление вместо master:
A--B--F--G master
\
C--D--E feature
\
H--I bugfix
Я хочу «переместить» эти коммиты, bugfixчтобы они больше не зависели feature. Таким образом, любой вид слияния или перебазирования, показанный выше в этом ответе, примет три featureкоммита вместе с двумя bugfixкоммитами.
Например, git rebase master bugfixэто неправильно. Диапазон, <start>который <end>случается, включает все коммиты feature, которые воспроизводятся поверх master:
A--B--F--G master
\ \
\ C'--D'--E'--H'--I' bugfix
\
C--D--E feature
То , что мы на самом деле хотим диапазон коммитов от featureдо bugfixбыть переигран на вершине master. Вот для чего --onto- указание цели «воспроизведения», отличной от ветви «start»:
git rebase --onto master feature bugfix
A--B--F--G master
\ \
\ H'--I' bugfix
\
C--D--E feature