Русский
Русский
English
Статистика
Реклама

Перевод Хватит копировать, пора сливаться. Часть 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", но проблема в том, что никакого "частичного" слияния нет.


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


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

Источник: habr.com
К списку статей
Опубликовано: 17.02.2021 16:08:10
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Git

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru