Как автоматически объединить .hgtags в Mercurial? - PullRequest
19 голосов
/ 20 марта 2012

У меня есть скрипт, выполняющий некоторые команды Mercurial в неинтерактивном режиме на сервере сборки.Одна из команд объединяет две ветви, и во время объединения всегда возникает конфликт в файле .hgtags из-за способа настройки сценариев сборки.

Как заставить Mercurial всегда объединять .hgtags файл, использующий изменения из обоих файлов, сначала из одного, а затем из другого?

Например, если файлы для слияния были

A
B
C

и

A
B
D

Я бы хотел, чтобы результат был

A
B
C
D

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

Ответы [ 5 ]

31 голосов
/ 20 марта 2012

Пожалуйста, смотрите ответ ниже от Magras de La Mancha для лучшего решения с Mercurial 3.1. Ниже приведено более простое и наивное решение для более старых версий Mercurial.


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

Конфликты в файле .hgtags могут иметь два типа:

  • Глупые конфликты: Это ваша ситуация, и здесь нет никакого конфликта. То, что происходит, - то, что у одной ветви есть

    f40273b0ad7b3a6d3012fd37736d0611f41ecf54 A
    0a28dfe59f8fab54a5118c5be4f40da34a53cdb7 B
    12e0fdbc57a0be78f0e817fd1d170a3615cd35da C
    

    , а другая ветвь имеет

    f40273b0ad7b3a6d3012fd37736d0611f41ecf54 A
    0a28dfe59f8fab54a5118c5be4f40da34a53cdb7 B
    979c049974485125e1f9357f6bbe9c1b548a64c3 D
    

    Каждый тег относится только к одному набору изменений, поэтому здесь нет конфликта. Конечно, объединение должно быть объединением одного из двух файлов:

    f40273b0ad7b3a6d3012fd37736d0611f41ecf54 A
    0a28dfe59f8fab54a5118c5be4f40da34a53cdb7 B
    12e0fdbc57a0be78f0e817fd1d170a3615cd35da C
    979c049974485125e1f9357f6bbe9c1b548a64c3 D
    
  • Реальные конфликты: Там одна ветка имеет

    f40273b0ad7b3a6d3012fd37736d0611f41ecf54 A
    0a28dfe59f8fab54a5118c5be4f40da34a53cdb7 B
    12e0fdbc57a0be78f0e817fd1d170a3615cd35da C
    

    , а другая ветвь имеет

    f40273b0ad7b3a6d3012fd37736d0611f41ecf54 A
    0a28dfe59f8fab54a5118c5be4f40da34a53cdb7 B
    979c049974485125e1f9357f6bbe9c1b548a64c3 C
    

    Здесь есть реальный конфликт: hg tag C было сделано в обеих ветвях, но теги относятся к различным наборам изменений. Решение этой проблемы выполняется вручную.

Если вы можете гарантировать, что у вас будут только глупые конфликты и что у вас будет только один тег на набор изменений, тогда вы можете использовать

hg log -r "tagged()" --template "{node} {tags}\n" > .hgtags

для создания нового .hgtags файла. Главное, что Mercurial знает, как объединить теги внутри! Он делает это все время, когда у вас есть две головки с разными .hgtags файлами. Приведенный выше шаблон просто генерирует новый файл .hgtags на основе этого внутреннего слияния.

Если у вас может быть более одного тега на набор изменений, вышеописанное не сработает - все теги печатаются в одну строку, поэтому вы получаете тег foo bar вместо двух тегов foo и bar. Затем вы можете использовать этот файл стиля вместо:

changeset = "{tags}"
tag = "{node} {tag}\n"

Выводит одну строку на тег , а не набор изменений. Вы сохраняете этот стиль где-то и настраиваете инструмент слияния:

[merge-tools]
hgtags.executable = hg
hgtags.args = log -r "tagged()" --style ~/tmp/tags-style > $output
hgtags.premerge = False
hgtags.priority = -1000

[merge-patterns]
.hgtags = hgtags

Теперь у вас есть автоматическое слияние тегов. Есть несколько предостережений:

  1. Три или более голов: Техника работает, только если у вас есть две головы на момент слияния. Если у вас три головы или более, удаленный тег может появиться снова. Если у вас есть главы X, Y и Z, а тег A удален в X, то Mercurial обычно может определить, что A удалено в целом. Он делает это на основе строки 000...0 A в файле .hgtags в X. Однако, если вы объедините X и Y, чтобы получить W, тогда предложенный подход не будет содержать такой строки 000...0 A. Определение A от Z теперь внезапно вступит в силу и вновь введет A.

  2. Реальные конфликты: Если у вас есть реальные конфликты в .hgtags, то вышеуказанный метод автоматически выберет для вас тег из самой последней головы . Инструмент слияния в основном сохраняет hg tags в .hgtags, а поведение hg tags с несколькими головками объяснено в вики . Так как hg tags безоговорочно читает и молча объединяет файл .hgtags со всех голов, мы ничего не можем с этим поделать с этим простым подходом. Чтобы справиться с этим, потребуется большой скрипт, который читает два файла .hgtags и обнаруживает конфликт.

11 голосов
/ 24 сентября 2014

Введена Mercurial 3.1 (2014-08-01) внутренняя: tagmerge . Он помечен как экспериментальный, поэтому будьте осторожны. Вот преамбула из changeset (вы можете найти более подробную информацию об алгоритме, перейдя по ссылке):

Добавление нового внутреннего инструмента слияния tagmerge, в котором реализован алгоритм автоматического слияния для файлов тегов mercurial

Алгоритм tagmerge способен разрешать большинство конфликтов слияния, которые в настоящее время вызывают конфликт слияния .hgtags. Единственный случай, который он не обрабатывает (и не может) обрабатывать, - это когда два тега указывают на разные ревизии у каждого родителя слияния и , их соответствующие истории тегов имеют одинаковый ранг (то есть одинаковую длину). Во всех остальных случаях алгоритм объединения выберет ревизию, принадлежащую родителю с историей тегов с наивысшим рейтингом. Объединенная история тегов представляет собой комбинацию обеих историй тегов (особое внимание уделяется тому, чтобы попытаться объединить общие истории тегов, где это возможно).

Алгоритм также обрабатывает случаи, когда теги были вручную удалены из файла .hgtags, и другие подобные угловые случаи.

В дополнение к фактическому объединению тегов от двух родителей с учетом базы алгоритм также пытается минимизировать разницу между файлом объединенного тега и файлом тега первого родителя (т. Е. Он пытается сделать порядок объединенных тегов как как можно ближе к порядку файлов тегов первого родителя).

tagmerge работает только с файлами тегов, поэтому для его использования необходимо установить merge-pattern . Чтобы сделать это для каждой команды, используйте - config option:

hg merge -r REV --config merge-patterns..hgtags=internal:tagmerge

Или, чтобы сделать это для каждого репозитория, добавьте в свой репозиторий .hg/hgrc это:

[merge-patterns]
.hgtags=internal:tagmerge
2 голосов
/ 20 марта 2012

На самом деле вам не нужно объединять файл .hgtags. В разных ветках он может быть разным, и Mercurial правильно перечислит все теги во всех ветках.

Мы используем параметр конфигурации merge-patterns , чтобы сообщить Mercurial об использовании локальной ветви при выполнении слияния .hgtags. Добавьте следующее в файл hgrc вашего репозитория:

 [merge-patterns]
 .hgtags = internal:local

При объединении файла .hgtags .hgtags будет отображаться как измененный, но не будет изменен.

1 голос
/ 20 марта 2012

Вы не можете автоматически разрешать конфликты слияний, выполняя автоматическое слияние. Без слияния (т. Е. Выбирая «только мое» или «только другое») это будет работать.

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

Но я полагаю, точные данные внутри .hgtags должны иметь значение для build-сервера (он использует собственный клон, никому не населенный, я надеюсь ?!), таким образом, вы можетеопределить любую политику слияния в команде и иметь (плохо, с потерей данных) .hgtags слил

Кстати, «сначала из одного, затем из другого» на любом языке, используя только формальную логику для пары

A
B
C

и

A
B
D

означает ABCABD результат

0 голосов
/ 20 марта 2012

Вы должны попробовать diffmerge , это круто!

...