Если вы помните, что git rebase
- это последовательность git cherry-pick
операций, 1 плюс пара полезных уловок в начале и конце, это имеет больше смысла.
Представьте, что у вас есть следующие серии коммитов:
...--o--*--...--o <-- mainline
\
A--B--C <-- feature
Вы хотите обновить feature
до mainline
, чтобы вы:
git checkout feature
git rebase mainline
Git начинает с перечисления коммитов, достижимых с feature
(C
, B
, A
, *
, ...) и коммитов, доступных с mainline
(без имени, ..., *
, ...). Он вычитает набор mainline
из набора feature
2 и использует обратный топологический порядок, так что теперь у него есть хэш-идентификаторы A
, B
и C
, перечисленные в том, что Git вызывает секвенсор . (Секвенсор также записывает операцию, в данном случае rebase / cherry-pick. Секвенсор также используется для нескольких возвратов. Секвенсор может остановиться на полпути, а затем возобновить с помощью --continue
. Поэтому ему необходимо знать операцию : продолжаем ли мы вишню, возвращение или ребаз?)
Затем Git отсоединяет HEAD
при коммите в конце mainline
и запускает операцию, какой бы она ни была, через секвенсор. Поскольку операцией является «rebase», каждый шаг секвенсора представляет собой простой вишневый выбор с одним коммитом:
(with)
...--o--*--...--o <-- mainline, HEAD
\
A--B--C <-- feature
(execute git cherry-pick A to produce)
A' <-- HEAD
/
...--o--*--...--o <-- mainline
\
A--B--C <-- feature
Может произойти сбой при конфликте слияния. Если это так, секвенсор останавливается, оставляя беспорядок конфликтов слияния в вашем индексе и рабочем дереве. Вы можете исправить их и возобновить работу секвенсора (который обязуется сделать A'
, если необходимо, если вы сами не сделали A'
), или выбрать один из двух видов останова: «прервать» или «выйти» , Если вы возобновите - или если дела пошли хорошо - мы продолжим (пытаться) черри B
:
A'-B' <-- HEAD
/
...--o--*--...--o <-- mainline
\
A--B--C <-- feature
Допустим, это также успешно, и мы продолжаем пытаться выбрать вишню C
, но эта попытка не удалась . Секвенсор останавливается, оставляя беспорядок в вашем индексе и рабочем дереве, с тем же графиком, который мы видим выше: A'
и B'
существуют, но C'
не существует.
Скажем, мы решили прекратить: завершить пикировку C
на данный момент слишком сложно, и нам нужно немного отступить и сделать что-то еще. Теперь у вас есть две опции: прервать или выйти .
Если вы выбираете --abort
, Git повторно присоединяет ваш HEAD
к feature
, давая:
...--o--*--...--o <-- mainline
\
A--B--C <-- feature (HEAD)
Где A'
и B'
? Что ж, если вы знаете, что делаете, вы можете выловить их из повторных флагов, или вы уже умело прикрепили название ветви или тега к B'
до , выбрав --abort
. Но если вы выберете --quit
, Git прекратит ребазу , не двигаясь HEAD
, так что вы получите:
A'-B' <-- HEAD
/
...--o--*--...--o <-- mainline
\
A--B--C <-- feature
но чистый индекс и рабочее дерево. Таким образом, у вас нет , чтобы быть достаточно умным, чтобы прикрепить имя ветви до --quit
.
Это в основном все, что нужно сделать. :-) Но после долгой и разочаровывающей перебазировки с партией конфликтов, где вы хотите сохранить достигнутые результаты и вернуться к работе без перебазирования, прежде чем снова вернуться к перебазировке позже вариант "бросить курить" кажется более удовлетворительным.
(Я думаю, что здесь действительно отсутствует опция сохранения оставшейся части состояния секвенсора и его восстановления позже. Однако, состояние секвенсора является для каждого рабочего дерева, так что если у вас есть текущая задача перебазирования и вам нужно ее прервать с задачей с более высоким приоритетом вы можете просто добавить рабочее дерево для задачи с более высоким приоритетом. Различные ошибки в добавленных рабочих деревьях через Git 2.15 не так уж внушают доверие, но, похоже, они теперь ведут себя хорошо. -деревья также накладывают на другую, более крупную недостающую часть, которая является способностью сохранить конфликтующее слияние в процессе и восстановить его позже.)
1 Обратите внимание, однако, что неинтерактивный git-rebase--am
старого стиля все еще использует git format-patch
и git am
.Этот процесс не работает в некоторых случаях с переименованными файлами и не может скопировать коммит "не вносит изменений", но он работает быстрее .В большинстве случаев как этот, так и стиль выбора «вишня» должны давать одинаковые результаты, несмотря на изменение базового механизма, тем более что вариант «выбор вишни» по умолчанию не копирует коммит «не вносит изменений».
2 Перебазировка также вычитает любые коммиты, которые существуют в наборе mainline
и имеют те же git patch-id
, что и любые коммиты в наборе feature
, и, конечно,по умолчанию вычитает все слияния.