Стратегия слияния Mercurial против стратегии слияния Git

Я использовал git в течение многих лет и недавно переключился на mercurial для проекта. За последние 6 месяцев я довольно хорошо научился использовать Mercurial через командную строку.

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

Я провел довольно много исследований, чтобы увидеть, что может отличаться в алгоритмах слияния, но с очень небольшим успехом. Большинство статей представляют собой мнения людей и информацию о том, как git и mercurial работают под капотом, без особого внимания к самим алгоритмам слияния и преимуществам/недостаткам с простыми примерами различий.

Я всегда использую хорошие стратегии слияния и объединяюсь вверх по дереву и никогда не спускаюсь в ветку по умолчанию (hg)/master (git) без предварительного слияния с удаленным сервером, чтобы убедиться в отсутствии конфликтов.

То, что я нашел до сих пор в своем исследовании, это:

1) Mercurial не может объединиться или имеет проблемы с объединением нескольких родителей. Я не уверен, как кто-то оказывается в такой ситуации, но, может быть, это обычное дело?

Это правда? Не вызовет ли это более частые конфликты слияния в повседневной разработке?

2) Mercurial не поддерживает слияние осьминогов, в отличие от git.

Для слияния осьминогов я говорю "какая разница!", это не обязательно.

Кроме этого, кажется, что алгоритмы слияния созданы одинаково? Можно ли изменить алгоритмы слияния? Есть ли отличные статьи на эту тему?

Если вы публикуете информацию об инструментах слияния, таких как k3diff, p4merge и meld, вы упускаете суть — мне нужна информация о стратегиях автоматического слияния до разрешения конфликта.

Спасибо за любые полезные ссылки и/или информацию!


person TheJeff    schedule 29.03.2018    source источник
comment
Чем ваш №1 отличается от №2? Слияние с несколькими родителями — это слияние осьминогов.   -  person max630    schedule 29.03.2018
comment
Не могли бы вы привести несколько примеров?   -  person max630    schedule 29.03.2018
comment
@ max630: Я почти уверен, что он имеет в виду несколько баз слияния, а не несколько родителей, в пункте № 1 (и это то, к чему я обращался в своем ответе).   -  person torek    schedule 29.03.2018
comment
Хороший вопрос на интересную тему.   -  person ryanwc    schedule 13.10.2018
comment
Я обнаружил, что важно обращать внимание на окончания строк, автоматическое форматирование и пробелы. Везде, от рассмотрения вашей IDE до вашей операционной системы, может повлиять на интерпретацию буквальных данных программой git. Я бы рекомендовал разные шаги для программ Mac, программ для Windows и программных проектов с несколькими ОС. Настройка Git auto-crlf = true не так хорошо работает, например, в проектах, совместно используемых Mac и Windows. Я НЕ переключался обратно на mercurial, чтобы анализировать похожие проблемы или варианты предпочтений после этого поста.   -  person TheJeff    schedule 06.12.2020


Ответы (1)


1) Mercurial не может объединиться или имеет проблемы с объединением нескольких родителей. Я не уверен, как кто-то оказывается в такой ситуации, но, может быть, это обычное дело?

Это правда? Не вызовет ли это более частые конфликты слияния в повседневной разработке?

Нет, это неправда — по крайней мере, как утверждается, что кажется немного бессмысленным.

Основная проблема при выполнении слияния на основе графа коммитов связана с поиском наименьшего общего предка или LCA. В дереве всегда есть один LCA, так что это очевидный вход для трехстороннего слияния: это основа в обычном базовом коммите, левосторонний/локальный/--ours коммит, правый- боковое / удаленное / --theirs управление.

Однако в группе DAG фиксации может быть более одного узла LCA. Стандартное решение Mercurial для этого состоит в том, чтобы выбрать один более или менее произвольно. Решение Git по умолчанию состоит в том, чтобы выбрать все из них и объединить их, используя стратегию -s recursive. Это «внутреннее» слияние приводит к единственному окончательному коммиту, который Git затем использует в качестве базы слияния. Вы можете переопределить это, чтобы сделать то же самое, что делает Mercurial, используя -s resolve: выбрать один более или менее произвольно и использовать его в качестве основы.

У Mercurial есть несколько экспериментальных альтернативных стратегий слияния (см., например, BidMerge), но ни одна из них не включена " из коробки», в отличие от четырех стратегий -s Git.

Множественные базы слияния возникают в основном, когда кто-то выполняет «перекрестное слияние». См. Как возникают перекрестные слияния в Git? В некоторых рабочих процессах это должно никогда происходить. , а на практике бывает не так уж и часто.

2) Mercurial не поддерживает слияние осьминогов, в отличие от git.

Для слияния осьминогов я говорю "какая разница!", это не обязательно.

Это правильно. Любое слияние осьминогов можно смоделировать серией попарных слияний. Однако они особенно хороши для хвастовства. :-)

Кроме этого, кажется, что алгоритмы слияния созданы одинаково?

Нет, потому что Mercurial и Git используют разные алгоритмы для отслеживания имен файлов. Проблема здесь в следующем: когда у вас есть три входа для трехстороннего слияния, кто говорит, что файл path/to/f в базе является тот же файлом, что и path2/f2 слева сбоку и/или path3/f3 справа? Какие файлы мы должны соединить или идентифицировать, как мне нравится это называть?

Ответ Mercurial на это заключается в отслеживании идентичности файла с помощью manifest и записанных операций с каталогами (записанных переименований или копий), в то время как Git определяет идентичность файла динамически посредством сопоставления содержимого. Однако полное динамическое определение требует слишком больших вычислительных ресурсов, поэтому Git обманывает: если два файла имеют одинаковый путь в base-vs-left или base-vs-right, эти два файла идентифицируются как «одинаковые». " файл. Это оставляет только имена путей без пары для динамической идентификации.

Нужно также решить, какое имя пути использовать в конечном результате. Здесь Mercurial заставляет вас выбирать во время выполнения команды слияния, в то время как Git просто помещает все имена в свой индекс, разрешая отложенный выбор имен после этого.

Однако после соответствующей идентификации и имени сам процесс слияния остается прежним: выясняется, какая сторона (стороны) изменила какой файл (файлы). Если только одна сторона изменила файл, используйте версию этой стороны. В противном случае выполните слияние на уровне файлов (Git называет это слиянием на низком уровне) для трех входов. Для этого требуется либо вычисление различий, либо отслеживание и объединение отдельных наборов изменений, и Git, и Mercurial выбирают прямой метод «база различий против наконечника». (Поскольку Git всегда хранит моментальные снимки, это отчасти принудительно. Mercurial иногда хранит моментальные снимки, так что это тоже своего рода принудительно.) Однако их внутренние механизмы сравнения также не идентичны, так что это тоже может дают несколько иные результаты.

Можно ли изменить алгоритмы слияния? Есть ли отличные статьи на эту тему?

Да: Git имеет -s аргументов, а Mercurial полностью подключается внутри.

Нет, насколько я знаю. Я работаю над книгой, за исключением того, что не работаю активно в наши дни у меня другая работа, и она не предназначена конкретно для них; но теоретические главы (которые, по крайней мере, почти готовы) дают соответствующую основу.

person torek    schedule 29.03.2018