Каково фактическое использование SVN mergeinfo?

Я давно слышал о проблемах слияния svn.

я испытал облегчение, когда узнал, что svn пару релизов назад реализовал функцию под названием mergeinfo. Казалось, что его введение позволит svn иметь достаточно информации для решения своих проблем слияния, когда бы они ни появились. Пока не попал в следующую ситуацию:--6-->

enter image description here

пример сценария приведенного выше графика:

SVN=${SVN:-svn}
SVNADMIN=${SVNAMDIN:-svnadmin}

rm -rf repo wc

$SVNADMIN create repo

$SVN co file://$PWD/repo wc
cd wc

# r1
$SVN mkdir trunk branches
$SVN ci -m 'structure'
$SVN up

# r2
echo 2 > trunk/t.txt
$SVN add trunk/t.txt
$SVN ci -m 'add t.txt'
$SVN up

# r3
$SVN cp trunk branches/A
$SVN ci -m 'create branch A'
$SVN up

# r4
echo 4 > branches/A/a.txt
$SVN add branches/A/a.txt
$SVN ci -m 'add a.txt'
$SVN up

# r5
$SVN cp trunk branches/B
$SVN ci -m 'create branch B'
$SVN up

# r6
echo 6 > branches/B/b.txt
$SVN add branches/B/b.txt
$SVN ci -m 'add b.txt'
$SVN up

# r7
$SVN merge ^/branches/B branches/A
$SVN ci -m 'merge branch B into A'
$SVN up

# r8
echo 8 > branches/A/d.txt
$SVN add branches/A/d.txt
$SVN ci -m 'add d.txt'
$SVN up

# r9
$SVN merge ^/branches/A branches/B

если svn держит история того, откуда берется каждая ветвь, почему она не может понять, что b.txt осталась нетронутой @ branch A?

если он не может понять это, какое фактическое использование svn делает из mergeinfo?

если svn не способен справиться с этой проблемой, не было бы возможно создать инструмент, чтобы помочь мне (а именно автоматическое решение такого рода проблем без проблем.. на этом фронте? Я думаю, уже будет существовать?

спасибо

3 ответов


в Subversion существует два типа слияния:

  1. трехточечные слияния
  2. двухточечные слияния (он же реинтеграционное слияние)

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

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

Subversion затем объединит изменения на магистрали без перезаписи изменений, сделанных на ветке. Стандартная процедура слияния и Subversion делает это довольно хорошо.

где svn:mergeinfo войти? Вы не хотите объединять дважды одинаковые изменения, поэтому Subversion отслеживает изменения с помощью svn:mergeinfo собственность. Если Subversion увидит, что изменение в магистрали из версии 5 уже было объединено, оно не будет восстанавливать это изменение. Это очень хорошо.

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

вот небольшая проблема. Мы отслеживали, что мы слили из ствола в ветку функции через svn:mergeinfo. Однако, поскольку мы не слились из ветви функции в магистраль, нет svn:mergeinfo там. Если мы попробуем обычное трехточечное слияние из ветви объекта в магистраль, магистраль будет предполагать, что все изменения в ветви объекта должны быть объединены обратно в магистраль. Однако многие из них особенности на самом деле изменения магистрали, которые были объединены.

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

перед Subversion 1.8, вам придется заставить реинтеграции слияния под управлением svn merge --reintegration. Теперь Subversion посмотрит на историю слияния и выяснит, когда должно быть сделано объединение реинтеграции.


теперь вот сложная часть. Внимательно посмотрите на номер версии. Это будет очень, очень важно!

  • редакция 10: я внес свои последние изменения в багажник, и мне нужно объединить их в функцию отделение.
  • редакция 11: я объединяю магистраль в ветвь функции. svn:mergeinfo покажет, что вся магистраль от версии 1 до версии 10 находится в ветви функции. Поскольку последнее изменение в trunk-это версия 10,это имеет смысл.
  • редакция 12: я объединяю ревизию 11 ветви функции в магистраль. Это реинтеграции слияние. После этого, что находится на ветке функции и что находится в багажнике, должно согласиться отлично.

теперь, вот Кикер!

  • пересмотр 13: я делаю еще одно изменение в багажнике.

теперь я хочу объединить это в свою ветвь функций (создание версии 14). Теперь, что делает svn:mergeinfo на ветку сказать? В нем говорится, что магистраль от версии 1 до версии 10 была объединена в ветвь функции. Однако ревизий 12 и 13 багажника не было. Поэтому Subversion захочет чтобы объединить ревизию 12 и ревизию 13 обратно в ветку функций.

Но постойте!

ревизия 12 на багажнике была моим слиянием всех изменений в моей ветви функции обратно в багажник! То есть версия 12 уже содержит все изменения, которые я внес в свою ветвь функций. Если я объединю ревизию 12 обратно в свою ветвь функций, я скажу, что все эти изменения в версии 12 на магистрали (которые действительно были внесены в ветвь объекта и объединена в магистраль) необходимо объединить в ветвь объекта. Но эти изменения были также внесены в ветку Feature. Можно ли сказать, что конфликт слияния? Я знал, что ты сможешь!


есть два способа справиться с этим:

  • рекомендуется: после реинтеграции ветви функции обратно в ствол, удалите ветку. Запереть ее. Никогда не используйте его снова. Не трогай! Это не так плохо, как кажется. После реинтеграции слияние, ваш ствол и эта ветвь функции будут соответствовать в любом случае. Удаление и воссоздание ветви из ствола не будет таким уж плохим.
  • хитрый способ, который работает: что нам нужно сделать, так это обмануть Subversion, думая, что версия № 12 (или изменения слияния реинтеграции) уже была объединена в нашу ветку функций. Мы могли бы потусоваться с svn:mergeinfo собственность. И я всегда так делаю. Где написано trunk:1-11, Я бы вручную изменить его trunk:1-12.

    Это сложно, но слишком сложно и рискованно, потому что Subversion уже дает вам способ манипулировать svn:mergeinfo без ручного изменения.

это называется запись только слияние.

$ svn co svn://branches/feature_a
$ cd feature_a
$ svn merge --record-only -c 12 svn://trunk
$ svn commit -m "Adding in the reintegration merge back into the feature branch."

это меняет svn:mergeinfo в ветви функций, не влияя на фактическое содержимое файлов. Настоящее слияние не выполняется, но Subversion теперь знает, что версия 12 магистрали уже находится в ветви функции. Однажды сделав это, вы можете повторно использовать ветку функций.


теперь посмотрите на свою диаграмму: когда вы объединили ветвь B В ветвь A, Вы объединили все изменения из B В A и svn:mergeinfo отследил. Когда вы объединяете ветвь B обратно в ветвь A, у вас уже есть все изменения из ветви B в ветви A, и вы не хотите, чтобы эти изменения были возвращены в ветвь B. Вы должны были использовать a реинтеграции слияние:

$ cd $branch_a_working_dir
$ svn merge $REPO/branches/B
$ svn commit -m "Rev 7: All of my changes on Branch B are now in A"
$ vi d.txt
$ svn add d.txt
$ svn commit -m"Rev 8: I added d.txt"
$ cd $branch_b_working_dir
$ svn merge --reintegrate svn://branch/A  # Note this is a REINTEGRATION merge!
$ svn commit -m"Rev 9: I've reintegrated Branch A into Branch B

теперь, если мы хотим продолжайте использовать ветвь A для дальнейших изменений:

$ cd $branch_a_working_dir
$ svn merge -c 9 --record-only $REPO/branches/b
$ svn commit -m"I've reactivated Branch A and can make further changes"

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

пока вы помните об этом, слияние Subversion работает довольно хорошо.


Дэвид В.!--10--> ответ довольно хорош, но я собираюсь предоставить свой собственный ответ, который ответит на это с более современным подходом. То, что Дэвид говорит вам, - правда, и полезно понять его ответ, читая мой ответ, поэтому вы должны сначала прочитать его, если вы еще этого не сделали. Мой ответ дает более современное понимание проблемы и решения проблем, на которые указывает Дэвид.

Итак, прежде всего, простой ответ заключается в том, что ситуация, которую вы представляете, работает просто хорошо, если вы используете Subversion 1.8. Пример сценария, который я добавил к вопросу, не имеет конфликта при запуске с помощью Subversion 1.8. Только клиент должен быть обновлен, чтобы получить эту функциональность.

более длинный ответ здесь заключается в том, что с более старыми версиями Subversion вам нужно знать, когда использовать плохо названный --reintegrate опция (1.8 выясняет это для вас). Несмотря на название --reintegrate не только для того, когда вы вернуть ветку обратно в багажник.

один из повторяющиеся проблемы, которые возникают у людей, когда они используют ветви объектов, заключаются в том, что они хотят объединить ветвь объектов обратно в свой ствол, а затем продолжить использование ветви. Как следует из ответа Дэвида, в прошлом было два метода борьбы с этим. Сначала удалите ветку, а затем сделайте ее свежей. Во-вторых, запись только сливается. Джулиан Фоуд, один из моих коллег разработчиков Subversion, при работе над 1.8 понял, что ни один из этих двух методов не был необходимый. Он покрыл это в его презентация о слиянии на конференции Subversion Live 2012. Слайды для его презентации доступны в интернете Здесь (обратите внимание, что это PDF-файл всех слайдов для конференции, поэтому он не совсем крошечный), часть об этих проблемах начинается на странице 123.

чтобы подвести итог его презентации, типичный рабочий процесс ветви функции заключается в создании ветви от магистрали. Принять совершает ветвь и периодически сливать из багажника ваша ветвь функции для синхронизации с тем, что находится на магистрали, например svn merge ^/trunk $BRANCH_WC. Затем, когда вы будете готовы к слиянию обратно в транк вы делаете svn merge --reintegrate ^/branches/myfeature $TRUNK_WC. Сейчас ты в точке, где традиционной мудрости пришлось удалить ветвь или сделать запись слить только. Вместо этого Джулиан обнаружил, что вы можете просто продолжать использовать ветку, если будете следовать этим правилам.

  • каждый раз, когда вы сливаетесь в том же направлении, что и последнее слияние между двумя ветвями, вы делаете не используйте . Рассматривайте создание ветви как слияние из этого места создания.

  • каждый раз, когда вы меняете направления, которые вы объединяете между двумя ветвями, используйте --reintegrate для этого слияния.

в вашем конкретном случае вы меняете направления, в которых вы сливаетесь. r7 сливается из ветви B в ветвь A. R9 сливается из ветви A в ветвь B. Поэтому, когда вы идете, чтобы сделать слияние r9, вам нужно использовать --reintegrate. Эта логика-именно то, что Subversion делает для вас с 1.8.

наконец, я не рекомендую сливаться между братскими ветвями, как вы делаете здесь. Много простых случаев, как то, что вы здесь делаете, будут работать хорошо. Однако, если вы, например, разделили файл (svn cp file file2, удалите часть file1 и другую часть из file2), тогда вы столкнетесь с проблемами при попытке объединить последнюю из двух ветвей функции обратно в магистраль (при условии, что вы объединили разделение на обе родственные ветви). Лучше всего ограничить слияние двумя ветвями (дочерней и родительской). Вы можете сделать ветви от других ветвей и слиться обратно к их родителю, прежде чем перейти к родителю родителя и так далее и быть в порядке. Мы хотели бы, чтобы даже такие вещи работали должным образом в будущем, но это ситуация, как сейчас в 1.8 (намного лучше, чем мы были в прошлом, но не так хорошо, как нам хотелось бы).


вы неправильно поняли значение и использование mergeinfo-он содержит только уже (для этого узла) объединенные ревизии и слияние-происхождение, чтобы не объединять ревизию дважды, ничего о содержании