Ответ 1
Вы не можете добраться отсюда (как сказал тот, кто дал указания). Точнее, это не имеет смысла.
Проблема заключается в том, что git merge --squash
фактически не выполняет слияние. Предположим, что ваша история ветвей выглядит, например (с ветвями topic
и devel
):
H ⬅ I ⬅ J <-- topic
⬋
⬅ F ⬅ G
⬉
K ⬅ L <-- devel
Если вы выберете devel
и смените topic
, вы получите новое слияние commit M
, которое содержит результат слияния, а M
имеет два родителя:
H ⬅ I ⬅ J <-- topic
⬋ ⬆
⬅ F ⬅ G ⬆
⬉ ⬆
K ⬅ L ⬅ M <-- devel
Но если вы используете git merge --squash topic
, вместо этого вы получаете новый фиксатор (пусть обозначают его S
для сквоша):
H ⬅ I ⬅ J <-- topic
⬋
⬅ F ⬅ G
⬉
K ⬅ L ⬅ S <-- devel
где (как вы уже отметили) содержимое (дерево) commit S
делает все файлы такими же, как и в commit M
. Но там нет обратной ссылки (родительская стрелка) от S до topic
. Это не слияние вообще, оно просто принимает все изменения от topic
, сбрасывая их в одно изменение и добавляя это как полностью независимую фиксацию.
Теперь, еще о git merge --squash
заключается в том, что он не делает окончательную фиксацию. Таким образом, вы можете создать файлы .git
, которые git будут использовать для "регулярного" слияния, и сделать фиксацию, в которой у вас есть два родителя с "реальным" слиянием. И тогда вы получите... точно то, что вы получите, если вы запустите git merge topic
, commit (отметьте его S
или M
, это не имеет значения), у которого есть то же дерево снова, но теперь имеет два родителя - стрелки, указывающие на L
и J
, как и на M
.
Фактически, запуск git merge --squash
почти точно совпадает с запуском git merge --no-commit
, за исключением файлов отслеживания, оставшихся после завершения слияния (git commit
использует некоторые из них для настройки родителей). Версия squash
не записывается в .git/MERGE
, .git/MERGE_HEAD
и .git/MERGE_MODE
. (Он создает .git/MERGE_MSG
, то же самое, что и git merge --no-commit
, а также создает .git/SQUASH_MSG
.)
Таким образом, в основном у вас есть выбор: реальное слияние (два или более родителей в финальной фиксации) или сквош (одни и те же механизмы объединения дерева, но только один родитель на конечной фиксации). И, поскольку git branch --merged
работает, глядя на "родительские стрелки" каждой фиксации, хранящейся в репозитории, только реальное слияние действительно является слиянием, поэтому только реальное слияние может быть обнаружено позже git branch
.