Давайте пропустить --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