Подтвердить что ты не робот

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

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

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

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

A
B
C

и

A
B
D

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

A
B
C
D

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

4b9b3361

Ответ 1

Обратитесь к ниже > 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

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

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

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

Ответ 2

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

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

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

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

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

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

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

Чтобы сделать это на основе каждого репозитория, добавьте в конфигурацию repo .hg/hgrc следующее:

[merge-patterns]
.hgtags=internal:tagmerge

Ответ 3

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

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

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

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

A
B
C

и

A
B
D

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

Ответ 4

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

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

 [merge-patterns]
 .hgtags = internal:local

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

Ответ 5

Вам следует попробовать diffmerge, это потрясающе!