Как автоматически объединить.hgtags в Mercurial?

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

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

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

A
B
C

а также

A
B
D

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

A
B
C
D

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

5 ответов

Решение

Пожалуйста, ознакомьтесь с ответом 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 файлы и обнаруживает конфликт.

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

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

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

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

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

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

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

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

[merge-patterns]
.hgtags=internal:tagmerge

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

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

 [merge-patterns]
 .hgtags = internal:local

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

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

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

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

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

A
B
C

а также

A
B
D

средства ABCABD результат

Вы должны попробовать отличиться, это круто!

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