SVN 1.8 слияние (повторное использование ветки) кажется поврежденным при наличии локальной mergeinfo
У нас проблема с новыми клиентами Subversion 1.8 (мы используем TortoiseSVN 1.8.5 и SlikSVN 1.8.5). Кажется, что новая функция SVN 1.8, заключающаяся в возможности продолжать использовать вашу ветвь функций после реинтеграции, в некоторых случаях не работает.
Это не работает, когда транк содержит локальную информацию mergeinfo (Mergeinfo для файлов или поддеревьев). Это может вызвать проблему для повторного использования ветви после реинтеграции. Это не было проблемой для 1.7 клиентов, если повторное использование ветки выполнялось с использованием "keep alive dance" (с использованием опции "только запись").
Я сделал скрипт, который иллюстрирует эту проблему с нуля. Его можно запустить с пустым хранилищем с помощью клиента 1.8.
Сценарий ниже имеет 10 шагов. Шаги 1-5 используются, чтобы создать начальную ситуацию с наличием локальной mergeinfo в транке. Шаги 6-9 имитируют изменения, которые вносятся в ствол в течение срока службы ветви функций2. Шаг 10 является ошибочным шагом, который имитирует первый шаг повторного использования функциональной ветви после реинтеграции.
Это ошибка в шаге 10:
svn: E195016: Reintegrate can only be used if revisions 8 through 11 were pre
viously merged from svn://svn2010/practice/branches/featurebranch2 to the reinte
grate source, but this is not the case:
trunk/file1.txt
Missing ranges: /trunk/file1.txt:9
Это (Windows) скрипт.
@ECHO OFF
ECHO ------------------------------------------------------------------
ECHO STEP 0: Create a repository
ECHO ------------------------------------------------------------------
if exist repo rmdir repo /S/Q
if exist trunk rmdir trunk /S/Q
if exist featurebranch1 rmdir featurebranch1 /S/Q
if exist featurebranch2 rmdir featurebranch2 /S/Q
svnadmin create repo --compatible-version 1.8
REM Make url based on current directory and replace backslashes by forward slashes
set url="file:///%cd:\=/%/repo"
ECHO url=%url%
ECHO ------------------------------------------------------------------
ECHO STEP 1: Create a trunk with 2 files
ECHO ------------------------------------------------------------------
svn mkdir -m "Create trunk" %url%/trunk
svn checkout %url%/trunk
echo Original file contents created in the trunk. > trunk\file1.txt
echo Original file contents created in the trunk. > trunk\file2.txt
svn add trunk\file1.txt
svn add trunk\file2.txt
svn -m "Added 2 files" commit trunk
ECHO ------------------------------------------------------------------
ECHO STEP 2: Create a copy (feature branch) from the trunk
ECHO ------------------------------------------------------------------
svn mkdir -m "Create branches dir" %url%/branches
svn copy -m "Create featurebranch1" %url%/trunk %url%/branches/featurebranch1
ECHO ------------------------------------------------------------------
ECHO STEP 3: Modify both files in the feature branch
ECHO ------------------------------------------------------------------
svn checkout %url%/branches/featurebranch1
echo Additional file contents created in featurebranch1. >> featurebranch1\file1.txt
echo Additional file contents created in featurebranch1. >> featurebranch1\file2.txt
svn -m "Modified 2 files in featurebranch1" commit featurebranch1
ECHO ------------------------------------------------------------------
ECHO STEP 4: Merge both files from featurebranch1 to the trunk to
ECHO create local mergeinfo on both files
ECHO ------------------------------------------------------------------
svn update trunk
svn merge %url%/branches/featurebranch1/file1.txt trunk/file1.txt
svn merge %url%/branches/featurebranch1/file2.txt trunk/file2.txt
svn -m "Merged 2 files from featurebranch1 to trunk" commit trunk
ECHO ------------------------------------------------------------------
ECHO STEP 5: Delete featurebranch2, we only needed it for the
ECHO initial setup
ECHO ------------------------------------------------------------------
svn delete -m "Delete featurebranch1" %url%/branches/featurebranch1
ECHO ------------------------------------------------------------------
ECHO STEP 6: This is the start of the problematic scenario
ECHO Create a new featurebranch2 from the trunk and a wc for it
ECHO ------------------------------------------------------------------
svn copy -m "Create featurebranch2" %url%/trunk %url%/branches/featurebranch2
svn checkout %url%/branches/featurebranch2
ECHO ------------------------------------------------------------------
ECHO STEP 7: Modify the contents of file1.txt in the trunk and leave
ECHO the contents of file2.txt unchanged (this is important)
ECHO ------------------------------------------------------------------
echo Additional file contents created in the trunk. >> trunk\file1.txt
svn -m "Modified file1.txt in the trunk" commit trunk
ECHO ------------------------------------------------------------------
ECHO STEP 8: Sync merge the trunk to featurebranch2
ECHO ------------------------------------------------------------------
svn update featurebranch2
svn merge %url%/trunk featurebranch2
svn -m "Sync merged the trunk into featurebranch2" commit featurebranch2
ECHO ------------------------------------------------------------------
ECHO STEP 9: Reintegrate featurebranch2 back into the trunk
ECHO ------------------------------------------------------------------
svn update trunk
svn merge %url%/branches/featurebranch2 trunk
svn -m "Reintegrated featurebranch2 back into the trunk" commit trunk
ECHO ------------------------------------------------------------------
ECHO STEP 10: Try to reuse featurebranch2 after it was reintegrated
ECHO Sync merge it from the trunk. THIS FAILS with SVN 1.8
ECHO ------------------------------------------------------------------
svn update featurebranch2
REM on SVN 1.7 we would use --record-only
svn merge %url%/trunk featurebranch2
:EOF
Я не понимаю, почему это происходит. Также в сообщении об ошибке отсутствуют диапазоны file1.txt, а в файле file2.txt отсутствует mergeinfo. Хотя это и не является решением, удаление локальной информации merge о файле file2.txt в транке также, похоже, решает проблему. Это также намекает на то, что сообщение об ошибке сообщает о неправильном файле.
Изменить: ответ на @gbjbaanb Эта проблема является более тонкой, чем та, на которую вы указываете, даже если сообщение об ошибке то же самое. В моем случае это не реинтеграция в магистраль, а сбой повторного использования ветки.
Также, если я посмотрю на mergeinfo файлов file1.txt и file2.txt, то, похоже, в file2.txt отсутствует запись mergeinfo файла featurebranch2, поэтому проблема заключается в том, что file2.txt, а не file1.txt, как предполагает ошибка. Поскольку file1.txt был изменен в транке во время жизни featurebranch2, а file2.txt не был mergeinfo о транке, не был задан в file2.txt во время слияния на шаге 8. Я считаю, что это место, где оно начинается сорвать. Это не повлияет на реинтеграцию в магистраль, но впоследствии предотвратит повторное использование ветви функций.
Редактировать: ответ на @David W Я пробовал --record-only -c 11, и это также работает на стороне Windows. Я уже пробовал это без -c (обычно вы не должны, я знаю, но в этом случае нет никаких других изменений), а затем он сообщает:
svn: E200004: The required merge is reintegrate-like, and the record-only option
cannot be used with this kind of merge
В качестве примера я также попробовал --record-only -c 1-11, что, как я и ожидал, будет таким же, как и использование -c (поскольку 11 - HEAD). Мое первоначальное ожидание состояло в том, что он потерпит неудачу так же, как и без использования -c, но это не так. Это удалось так же, как -c 11.
Но весь смысл моего поста в том, что с SVN 1.8 нам не нужно поддерживать хитрость. (ПРОЕКТ) документация гласит:
Если вы решите не удалять свою ветвь после реинтеграции ее в ствол, вы можете продолжить выполнять слияния синхронизации из ствола, а затем снова реинтегрировать ветку [37]. Если вы сделаете это, только изменения, сделанные в вашей ветке после первой реинтеграции, будут объединены в ствол. ( http://svnbook.red-bean.com/).
И из примечаний к выпуску Subversion 1.8:
Объединение туда-сюда между двумя ветвями в любом порядке возможно с помощью автоматического слияния реинтеграции ("танец поддержания жизни" больше не нужен). Для достижения наилучших результатов рекомендуется всегда объединять все допустимые ревизии, т. Е. Не использовать параметры -r или -c команды svn merge. Слияние только подмножества приемлемых ревизий увеличивает вероятность проблем во время будущих слияний. ( https://subversion.apache.org/docs/release-notes/1.8.html)
Поэтому я хочу сказать, что повторное использование этой ветки без хитрости поддержки активности не работает, несмотря на локальную информацию mergeinfo, и мой сценарий, кажется, показывает это.
Если вы все еще чувствуете, что предупреждение о пропущенных диапазонах может быть правильным, за исключением, возможно, сообщенных номеров диапазонов, пожалуйста, покажите мне, где в моем сценарии я вызываю пропущенный диапазон. Мой сценарий - это простой переход между стволом и ответвлением без параллельной работы с ними обоими.
Также не могли бы вы объяснить, почему также изменение file2.txt путем добавления: "echo Дополнительное содержимое файла, созданного в транке. >> trunk\file2.txt" к шагу 7, приведет к тому, что на шаге 10 не возникнет ошибка. Изменение дополнительного файла на стволе не может решить проблему отсутствующих диапазонов.
2 ответа
В списке рассылки Subversion: users@subversion.tigris.org было решено, что эта проблема заслуживает создания отчета о проблеме. Для получения дополнительной информации см.: Отчет о проблеме и список рассылки пользователей Subversion.
Редактировать:
Начиная с версии 1.8.9 это было исправлено (проблема № 4481). Спасибо!
Я не верю, что версия 1.8 решает проблему повторного использования веток. Проблема связана с нумерацией ревизий и тем, как Subversion отслеживает, где находится ревизия.
Давайте начнем с Revision 100. Я внес изменения в магистраль, и я хочу объединить все эти изменения в свою ветку. Я делаю стандартное слияние и создаю Revision 101 (на моей ветке). На моей ветке svn:mergeinfo
показывает, что все изменения в транке до и включая ревизию 100 теперь на моей ветке. Пока что моя последняя версия багажника - Revision 100. Все хорошо и хорошо.
Теперь я хочу вернуть свои изменения обратно в багажник. Я делаю слияние с реинтеграцией, которое выполняет двустороннее слияние, поэтому после слияния мой ствол теперь будет выглядеть как моя ветвь. Это ревизия 102, и она у меня на багажнике. До сих пор я слил Revision 100 в свою ветку, Revision 101 не находится на моем стволе, но теперь у меня есть Revision 102 на моем стволе.
Я сейчас внесу еще одно изменение в багажник. Это ревизия 103. Я решаю, что это необходимо и для моей ветки.
Моя ветка говорит, что все ревизии на транке до ревизии 100 были объединены с моей веткой. Все идет нормально. Теперь я сделаю еще одно слияние, и теперь у меня на стволе две новые ревизии: ревизия 102 и ревизия 103. Согласно svn:mergeinfo
изменения в обеих этих ревизиях должны быть объединены в мою ветку.
Но ждать! Ревизия 102 была слиянием реинтеграции от моей ветви до ствола. Эта информация уже есть в ветке. Слияние Revision 102 снова испортит мою ветку. Я, вероятно, получу массу конфликтов слияния.
У Subversion нет реального способа обнаружить эту проблему. Есть два способа решения этой проблемы:
- Никогда не используйте ветку или
- Сделать
svn merge --record-only -r102
записать, что ревизия 102 уже находится на ветке. Это не делает никаких изменений в файле (за исключением значения свойстваsvn:mergeinfo
).
Если вы сделали #2, теперь вы можете объединить свои изменения из магистрали обратно в ветку, потому что, svn:mergeinfo
будет сообщать, что все изменения в вашей магистрали вплоть до Revision 102 и в вашей ветке. Только изменения в Revision 103 должны быть внесены в вашу ветку.
Так в чем твоя проблема?
Subversion теперь может определять необходимость регулярного (трехстороннего) слияния и реинтеграции (двухстороннего) слияния. Вам больше не нужно использовать --reintegration
параметр.
Однако вы не сможете выполнить слияние с реинтеграцией, если вы ранее не слили все изменения, которые находятся в стволе, в вашу ветку.
Допустим, вы слили все ревизии из ствола в вашу ветку, за исключением ревизии 95. В вашей стволе содержится изменение в ревизии 95, но в вашей ветке этого изменения нет. Если я делаю свое слияние с реинтеграцией, я делаю двустороннее слияние. Я собираюсь сделать так, чтобы мой ствол соответствовал моей ветви - моей ветви, в которой нет изменений, которые вы сделали в Revision 95.
Если я сливаю свою ветку в мой ствол, я теряю изменения в Revision 95, которые я внес в свой ствол.
Вы не хотите, чтобы это произошло. Поэтому Subversion предупредит вас, если вы выполняете слияние реинтеграции, но не слили все изменения ствола обратно в ветку.
Давайте посмотрим на ваше сообщение еще раз:
svn: E195016: Reintegrate can only be used if revisions 8 through 11 were previously merged from svn://svn2010/practice/branches/featurebranch2 to the reintegrate source, but this is not the case:
trunk/file1.txt
Missing ranges: /trunk/file1.txt:9
Это говорит вам о том, что вы хотите реинтегрировать все свои изменения до Revision 11 обратно в свой ствол. Однако редакция № 9 так и не была объединена с веткой. Если вы выполните слияние с реинтеграцией, вы потеряете это изменение в своем стволе.
Чтобы продолжить, вам нужно либо использовать --force
(плохая идея), или сделайте другое объединение из ствола обратно в ветку, чтобы внести изменения в Revision 9 в вашу ветку.
Как только это будет сделано, вы можете выполнить слияние веток с транком.
Я надеюсь, что это проясняет ситуацию.
Unix версия вашего скрипта
Вот моя версия сценария. Он был более или менее переведен с Windows Batch на оболочку Bash. Основным отличием является:
- Шаг 9.5: Я нашел последнее изменение в стволе. Это ревизия, которую вы должны записать в своей ветви функций, чтобы использовать ее повторно.
- Шаг 10: я использую
--record-only
на ветви функций с-c
потому что вам нужно для того, чтобы повторно использовать вашу функциональную ветку. В Subversion 1.8 все работает отлично. Это прекрасно работает как на Mac OS X Mavericks, так и на RHEL 6. Я не пробовал это на 6.5.
Основное различие между SVN 1.7 и SVN 1.8 в этом сценарии состоит в том, что SVN 1.7 выполнил бы слияние без какого-либо предупреждения, в то время как SVN 1.8 пытается предупредить вас о проблеме. Я не уверен, почему сообщалось о 9-й редакции. Это было последнее слияние из этой ветви в транк, похоже, в сообщении следовало указать 11-ю ревизию, которая является ревизией, которая была реинтегрирована. Я полагаю, что ошибка связана с навыками инженерного языка больше, чем с какой-либо ошибкой.
Кстати, вместо запуска:
svn merge --record-only -c$last_changed $URL/trunk featurebranch2
Если бы я запустил это:
svn merge --force $URL/trunk featurebranch2
Слияние происходит так же, как и в Subversion 1.7. В этом случае слияние происходит правильно, но это потому, что вы не меняли файлы в стволе или ветви до того, как сделали окончательное слияние. Это была просто удача
#! /bin/bash
# svnscript.sh
#
# ECHO STEP 0: Create a repository
echo "Create Repository"
[[ -d "repo" ]] && rm -rf repo
[[ -d "trunk" ]] && rm -rf trunk
[[ -d "featurebranch1" ]] && rm -rf featurebranch1
[[ -d "featurebranch2" ]] && rm -rf featurebranch2
svnadmin create repo --compatible-version 1.8
URL="file://$PWD/repo"
echo "URL=$URL"
########################################################################
# STEP 1: Create a trunk with 2 files
########################################################################
echo "Step 1: Create a trunk with 2 files"
svn mkdir -m"Create trunk" $URL/trunk
svn checkout $URL/trunk
echo Original file contents created in the trunk. > trunk/file1.txt
echo Original file contents created in the trunk. > trunk/file2.txt
svn add trunk/file1.txt
svn add trunk/file2.txt
svn -m "Added 2 files" commit trunk
########################################################################
# STEP 2: Create co copy (feature branch) from the trunk
########################################################################
echo "STEP 2: Create a feature branch from the trunk"
svn mkdir -m "Create branches dir" $URL/branches
svn copy -m "Create featurebranch1" $URL/trunk $URL/branches/featurebranch1
########################################################################
# STEP 3: Modify both files in the feature branch
########################################################################
echo "STEP 3: Modify both files in the feature branch"
svn checkout $URL/branches/featurebranch1
echo "Additional file contents created in featurebranch1." >> featurebranch1/file1.txt
echo "Additional file contents created in featurebranch1." >> featurebranch1/file2.txt
svn -m "Modified 2 files in featurebranch1" commit featurebranch1
########################################################################
# STEP 4: Merge both files from featurebranch1 to the trunk
########################################################################
echo "STEP 4: Merge both files from featurebranch1 to the trunk to "
echo " create local mergeinfo on both files"
svn update trunk
svn merge $URL/branches/featurebranch1/file1.txt trunk/file1.txt
svn merge $URL/branches/featurebranch1/file2.txt trunk/file2.txt
svn -m "Merged 2 files from featurebranch1 to trunk" commit trunk
########################################################################
# STEP 5: Delete Feature1 branch: No longer needed
########################################################################
echo "STEP 5: Delete featurebranch2, we only needed it for the"
echo " initial setup"
svn delete -m "Delete featurebranch1" $URL/branches/featurebranch1
########################################################################
# STEP 6: This is the start of the problematic scenario
########################################################################
echo "STEP 6: This is the start of the problematic scenario"
echo " Create a featurebranch2"
svn copy -m "Create featurebranch2" $URL/trunk $URL/branches/featurebranch2
svn checkout $URL/branches/featurebranch2
########################################################################
# STEP 7: Modify the contents of file1.txt. in trunk
########################################################################
echo "STEP 7: Modify the contents of file1.txt in the trunk and leave"
echo " the contents of file2.txt unchanged (this is important)"
echo "Additional file contents created in the trunk." >> trunk/file1.txt
svn -m "Modified file1.txt in the trunk" commit trunk
########################################################################
# STEP 8:Sync merge the trunk to featurebranch2
########################################################################
echo "STEP 8: Sync merge the trunk to featurebranch2"
svn update featurebranch2
svn merge $URL/trunk featurebranch2
svn -m "Sync merged the trunk into featurebranch2" commit featurebranch2
########################################################################
# STEP 9: Reintegrate featurebranch2 back into the trunk
########################################################################
echo "STEP 9: Reintegrate featurebranch2 back into the trunk"
svn update trunk
svn merge $URL/branches/featurebranch2 trunk
svn -m "Reintegrated featurebranch2 back into the trunk" commit trunk
########################################################################
# STEP 9.5: Get the last change info on Trunk
########################################################################
svn update trunk
last_changed=$(svn info $URL/trunk | sed -n '/Last Changed Rev/s/.*: //p')
########################################################################
# STEP 10: Try to reuse featurebranch2 after it was reintegrated
# This time, we'll use the --record-only with the change on trunk
########################################################################
echo " STEP 10: Try to reuse featurebranch2 after it was reintegrated"
echo " Sync merge it from the trunk. THIS FAILS with SVN 1.8 "
svn update featurebranch2
svn merge --record-only -c$last_changed $URL/trunk featurebranch2
svn commit -m"It works on MY machine!" featurebranch2