Git branch --merged / --no-merged и опция --squash

git branch --merged Похоже, не очень хорошо играть с --squash.

Если вы делаете нормальный git merge, затем git branch --merged говорит вам, какие ветви были объединены. Однако это не тот случай, если используется опция --squash, даже если результирующее дерево одно и то же.

Я сомневаюсь, что это дефект мерзавца, и хотел бы знать, есть ли какой-то мерзавец, которого я пропускаю, или я что-то неправильно понял.

Короче говоря: я хочу использовать --squash, но также хочу, чтобы git сообщал мне, была ли ветвь, в которую я врезался, в другую.

1 ответ

Решение

Вы не можете добраться туда отсюда (как сказал парень, дающий указания). Точнее, это не имеет смысла.

Проблема в том, что git merge --squash на самом деле не делает слияние. Предположим, например, что история вашей ветки выглядит так (с ветками topic а также devel):

          H ⬅ I ⬅ J     <-- topic
        ⬋
⬅ F ⬅ G
        ⬉
          K ⬅ L         <-- devel

Если вы проверите devel и объединить topic Вы получаете новый коммит слияния 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

где (как вы уже отметили) содержимое (дерево) коммита S делает все файлы такими же, как и при коммите M, Но нет обратной ссылки (родительской стрелки) от S до topic, Это не слияние, а просто принятие всех изменений topicобъединяя их в одно изменение, и добавляя это как совершенно независимый коммит.

Теперь другая вещь о git merge --squash в том, что он не делает окончательный коммит. Таким образом, вы могли бы создать .git файлы, которые git будет выполнять при "обычном" слиянии, и делать коммит с двумя родителями, которых вы получите при "реальном" слиянии. И тогда вы получите... именно то, что вы получите, если запустить git merge topic, коммит (пометить его 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,

Другие вопросы по тегам