Хватит копировать, пора сливаться. Часть 2. Конфликт слияний, который так и не произошёл (а должен был)

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

В последний раз мы видели как изменение кода в скопированном коммите создаёт опасность конфликта, который сидит себе тихо пока обе копии где-нибудь не сольются, что может произойти и в очень отдалённом будущем. Но знаете что хуже, чем конфликт слияний?


Отсутствие любого конфликта.


Давайте вернёмся к прежней ситуации:


первое дерево


Представим что ветка "feature" существует уже давно и периодически сливается в "master". Диаграмма показывает срез дерева сразу после последнего слияния А. Мы работаем над спринтом в "feature", полным нового функционала.


Предположим, что строка "apple" находится в файле настроек, управляющим какой-то фичей. Обе ветки фиксируют коммиты M1 и F1, которые не трогают этот файл.


Теперь представим что мы нашли серьёзную ошибку в старой фиче, которая полностью рушит поведение всей программы. Резко пресекая проблему, мы выключаем фичу, меняя строку на "berry" и фиксируя изменения как F2.


В жизни произойдёт что-то похожее на изменение строки c


#define IS_FEATURE_ENABLED 1

на


#define IS_FEATURE_ENABLED 0

Но раз уж я начал использовать "apple" и "berry", пусть так они и останутся.


Хорошо, мы отключили фичу, проверили что теперь никаких проблем нет, и скопировали отключение в "master". Фух, теперь можно выдохнуть, кровотечение остановлено, у нас есть время подумать что пошло не так и как это чинить.


Можно также отключить фичу напрямую в "master", а затем скопировать коммит в "feature", картина будет той же.


Пока мы исследуем проблему, работа в "master" ветке продолжается. Позже мы чиним баг, включаем обратно фичу и фиксируем изменения как F3 в "feature" ветке. Дерево коммитов теперь выглядит так:


Баг исправлен


Новый несвязанный с "berry" коммит M3 был добавлен в ветку "master". В "feature" мы вернули обратно "apple" коммитом F3.


Теперь мы хотим слить ветку "feature" в "master" чтобы временное отключение фичи было заменено нормальным фиксом. Но вместо этого после слияния мы получаем такую картину:


Упс


Слияние породило коммит M4, но вопреки ожиданиям строка всё ещё содержит "berry". В "master" перекочевало временное отключение фичи! Даже хуже, в "master" теперь находятся оба фикса: как основной, так и временный. Вполне возможно они плохо друг с другом совмещаются, и появятся только новые баги. Получается, фича работает только в ветке "feature", а в "master" вообще непонятно что.


Разберёмся почему это произошло, в следующей статье я опишу как этого избежать.


Вернёмся к дереву коммитов до слияния:


Before merge


При слиянии Git смотрит на базу слияния (merge base): ближайшего родственника между двумя ветками, в нашем случае это коммит А. Затем Git выполняет трёх-стороннее слияние (three-way merge), используя А как базу, M3 как HEAD, а F3 как вливающееся изменение. Теперь нас интересует только дельта между базой и двумя последними коммитами, так что уберём вся лишнее из диаграммы:


simple


Сравнивая базу с верхушкой "master" ветки мы видим что "apple" поменялась на "berry". Сравнение с "feature" не даёт никаких изменений. Так как строка "apple" осталась прежней в "feature", слияние её в "master" также оставит всё как есть. В результате "master" будет содержать "berry" после слияния.


Но это ещё не всё, если затем слить "master" в "feature", то неверная строка "berry" распространится и в "feature":


incorrect


Это происходит потому, что теперь меняются местами принимающая и отдающая сторона. В основании (коммит А) строка "apple", в ветке "feature" она остаётся неизменной, но в неё вливают "berry" из "master". И здесь даже не важно, используется быстрая перемотка (fast-forward) или нет.


Многие думают о копировании коммитов как о "частичных слияниях, предвосхищающих будущее полное слияние", когда вам надо слить часть наработок в главную ветвь. Вы ожидаете, что позже, когда вы полностью сольёте исходную ветку в главную, сольются только новые наработки.


Если же вы настолько аккуратны, что не трогаете строк, задействованных при копировании, ожидания оправдаются. Иначе, вместо слияния вы получите наложение изменений друг на друга. Хуже того, если ваши изменения отменяют скопированные, то вы даже не получите конфликт при слиянии, который показал бы что что-то идёт не так. Внутри нашей команды мы называем это АБА проблемой, т.к. сначала строка содержала А, затем её поменяли на Б, Б скопировали, а затем вернули А прямо перед слиянием в "master".


Хорошо, вкратце получается мы хотели сделать частичное слияние из "feature" в "master", но проблема в том, что никакого "частичного" слияния нет.


Или всё же есть?


В следующей статье я покажу как его осуществить.

Источник: https://habr.com/ru/post/542914/


Интересные статьи

Интересные статьи

Одна из самых важных (на мой взгляд) функций в Битрикс24 это бизнес-процессы. Теоретически они позволяют вам полностью избавиться от бумажных служебок и перенести их в эл...
«— Скажите, пожалуйста, куда мне отсюда идти? — А куда ты хочешь попасть? — ответил Кот. — Мне все равно… — сказала Алиса. — Тогда все равно, куда и идти, — заметил Кот.» (С) «Алиса в стране ...
В 1996 году у меня наконец-то появилась возможность собрать свой компьютер. Материнку с процессором 486dx33 купил на митинском рынке за какие-то копейки, потому что она больше ни с чем не работал...
Ссылка на часть 2 В предлагаемой вашему вниманию публикации рассмотрены основы архитектуры, аппаратной структуры, и структуры системного ПО бортового компьютера миссий Apollo — AGC (Apollo Gui...
Данная статья продолжает рассмотрение вопроса, поднятого @olartamonov, а именно, обеспечение безопасности в высоковольтных приложениях. В статье будут рассмотрены физические основы пробоя диэлект...