Ответ 1
Это происходит из-за того, что Git не знает, что слияние сквоша эквивалентно "различным конкретным ветвям". Вы должны принудительно удалить ветвь с git branch -D
вместо git branch -D
.
(Остальное - это только то, почему это так).
Нарисуйте граф фиксации
Пусть нарисовать (часть) графа фиксации (этот шаг подходит для многих вещей в Git...). На самом деле, отпустите еще один шаг, чтобы мы начали с вашего git rebase
, с чем-то вроде этого:
...--o--o--o <-- mainline
\
A--B--C <-- feature1
Название ветки, например mainline
или feature1
, указывает только на одно конкретное коммит. Эта фиксация указывает назад (влево) на предыдущую фиксацию и т.д., И это эти обратные указатели, которые формируют фактические ветки.
Верхняя строка коммитов, всего лишь называемая o
здесь, немного скучна, поэтому мы не дали им буквенных названий. Нижняя строка commits, A-B-C
, находится только на ветке feature1
. C
- самая новая такая фиксация; он возвращается обратно к B
, что возвращается к A
, что приводит к одному из скучных o
коммитов. (В стороне: крайняя левая o
фиксация вместе со всеми более ранними фиксациями в разделе ...
находится в обеих ветвях.)
Когда вы запустили git rebase
, три комманды A-B-C
были скопированы в новые коммиты, добавленные к кончику mainline
, давая нам:
...--o--o--o <-- mainline
\ \
\ A'-B'-C' <-- feature1
\
A--B--C [old feature1, now abandoned]
Новые комманды A'-B'-C'
в основном такие же, как и исходные три, но они перемещаются на графике. (Обратите внимание, что все три бурения o
совершаются на обеих ветвях сейчас.) Отказ от оригинала три означает, что Git обычно не нужно сравнивать копии с оригиналами. (Если оригиналы были доступны другому имени - ветвь, добавленная к старому feature1
, например, Git, может понять это, по крайней мере, в большинстве случаев. Точные сведения о том, как Git показывает это здесь нет особого значения.)
В любом случае, теперь вы запускаете git checkout mainline; git merge --squash feature1
. Это делает одно новое коммитирование, которое является "сквош-копией" трех или даже многих коммитов, находящихся на feature1
. Я прекращу рисовать старые заброшенные и вызовет новый squash-commit S
для Squash:
...--o--o--o--S <-- mainline
\
A'-B'-C' <-- feature1
"Удалить безопасность" полностью определяется историей фиксации
Когда вы запрашиваете Git для удаления feature1
, он выполняет проверку безопасности: "feature1
объединено в mainline
?" Это "сливается в" тест основан исключительно на связности графа. Имя mainline
указывает на фиксацию S
; commit S
указывает на первый расточный o
фиксация, которая возвращает к более скучной o
фиксации. Commit C'
, кончик feature1
недоступен из S
: нам не разрешено двигаться вправо, только влево.
Сравните это с созданием "нормального" слияния M
:
...--o--o--o---------M <-- mainline
\ /
A'-B'-C' <-- feature1
С помощью одного и того же теста: "является ли фиксация наконечника feature1
достижимой от фиксации наконечника mainline
?" - ответ теперь да, потому что commit M
имеет ссылку вниз и левую для фиксации C'
. (Commit C'
есть в Git внутреннем выражении, второй родитель слияния commit M
.)
Так как слияния сквоша фактически не сливаются, но нет связи от S
назад к C'
.
Опять же, Git даже не пытается увидеть, является ли S
"таким же, как" A'
, B'
или C'
. Однако, если бы это было так, то было бы сказано "не то же самое", потому что S
совпадает с суммой всех трех коммитов. Единственный способ получить S
для соответствия раздавленным коммитам - это иметь только одну такую фиксацию (и в этом случае нет необходимости раздавить в первую очередь).