Подумайте над этим риторическим вопросом: какую отвертку использовать на гвозде, плоской головке или крестообразной головке?
Практически несколько: все, что делает git rebase
, это копия (некоторый набор) фиксирует, а затем возвращает имя ветви.То есть, за до git rebase
у вас может быть:
...--F--G--H <-- master
\
I--J--K <-- feature
Вы запускаете git checkout feature; git rebase master
с целью: заменить существующие коммиты I-J-K
новой серией коммитов, скопированный с I
, J
и K
, так что новые и улучшенные коммиты выглядят так:
I'-J'-K' <-- feature
/
...--F--G--H <-- master
\
I--J--K [abandoned]
Это разумно сделать какПока никто не использует I-J-K
.Если ни у кого нет их, это можно сделать в любое время.Если у Боба и Кэрол они есть, но они не используют их , и вы можете убедить Боба и Кэрол переключиться на новые коммиты замены, не прерывая их работу вообще, это все еще безопасночтобы сделать, но теперь вы должны координировать свои действия с двумя другими людьми.
В некоторых случаях это может быть разумным, даже если другие используют исходную цепочку и зависят от нее.Здесь они должны знать, как обращаться с их коммитами, потому что теперь они имеют свои собственные дополнительные коммиты в их репозиториях:
...--F--G--H <-- master
\
I--J--K <-- feature
\
L <-- bob
После того, как вы замените I-J-K
новым и улучшенным I'-J'-K'
, Бобу придется заменить свой собственный L
своим собственным новым и улучшенным L'
.Что может быть в порядке, но хорошо бы уточнить это с Бобом, прежде чем делать это.
А как насчет объединенного PR?
Вот где все становится особенносложный, особенно если люди используют кнопки «перебазировать и объединить» или «сквош и объединить» на GitHub.
Кнопка перебазировать-и-объединить на GitHub заставляет GitHub сделать ту же заменутрюк.То есть они берут вашу I-J-K
цепочку и копируют ее. Они делают это, даже если для этого нет веской причины. То есть, предположим, что ваши коммиты выглядят так:
...--F--G--H <-- master
\
I--J--K <-- feature
Эта серия коммитов может простобыть добавленным на к существующим коммитам, имея имя master
, скользящее вниз и вправо в том, что Git называет быстрая перемотка вперед операция:
...--F--G--H
\
I--J--K <-- feature, master
Но GitHub этого не сделает.Когда вы (или кто-то другой) используете кнопку rebase-and-merge, вместо этого они будут делать:
I'-J'-K' <-- feature
/
...--F--G--H <-- master
\
I--J--K [your PR - abandoned]
Если у вас будет дополнительный коммит L
, который следует после K
, Вы теперь находитесь в той же позиции, что и Боб ранее.Вы должны скопировать свой L
в новый L'
, который следует после K'
, без повторного копирования I-J-K
.
Самое простое, что нужно сделать, это не , чтобы иметьL
вообще.Просто оставьте ветку с именем feature
(например, удалите ее целиком), обновите свой master
, чтобы выполнить коммит K'
, а затем снова создайте имя feature
, указывая на K'
:
...--F--G--H--I'-J'-K' <-- feature, master
Никто (включая вас) никогда не запомнит хеш-идентификаторы исходной цепочки I-J-K
, и вам будет "казаться, что" вы просто продолжаете с того места, на котором остановились, когда в конце концов делаете коммитL
, который следует после K'
:
...--F--G--H--I'-J'-K' <-- master
\
L <-- feature
Кнопка "squash and merge" работает во многом как кнопка "rebase and merge", за исключением того, что вместо копирования цепочки коммитов один коммит ввремя GitHub сделает один коммит с тем же эффектом , как если бы они скопировали коммиты:
...--F--G--H--IJK <-- master
, где коммит IJK
является результатом слияния K
(как будто через git merge
), но затем делает обычную однополую фиксацию (следовательно, больше как будто через git merge --squash
).Как и раньше, если у вас уже есть L
, который исходит от вашего оригинального K
, вы должны отказаться от L
в пользу новой копии L'
, которая приходит после нового коммита IJK
.
Если вы Боб
Вы можете использовать git rebase --onto
, чтобы делать подобные вещи относительно удобно, как только вы окажетесь в ситуации, которую мы изначально приписали Бобу, здесь. Опция --onto
позволяет вам сказать Git: помещать копии после моего обновленного master
, а также позволяет вам сказать Git: не копировать коммит K
или что-либо ранее, чем K
. Без --onto
ваш git rebase
принимает один аргумент, который является , куда помещать копии и , что не нужно копировать , и вам нужно отделить их .
В некоторых случаях Git действительно может придумать для вас подобные вещи. Вот что такое режим --fork-point
git rebase
, доступный (и по умолчанию!) Со времен Git версии 2.0. К сожалению, ни один из этих случаев не относится к GitHub и его кнопкам rebase-and-merge или squash-and-merge. В других случаях, один из которых применим , здесь Git может все еще понять это, но если вы видите много проблем с ребазой, это означает, что Git не понял, и вы, вероятно, хотите git rebase --onto
, если вы хотите git rebase
вообще.