Обновление субверсии на дату
Я работаю над большим, установленным проектом под управлением SVN. Многие части базы кода проверяются как внешние, но активно работают другие люди.
Я хотел обновить всю рабочую копию, внешние и все, чтобы она отражала HEADs различных репозиториев в определенный момент времени. Моя первоначальная попытка:
svn up -r'{20090324}'
Это обновляет текущий каталог до указанной даты, но обновляет все внешние данные до текущей даты. Обновление внешних ресурсов по одному работает так, как ожидалось.
Я понимаю, что из-за внешнего характера одно обновление не могло работать с номером ревизии, но почему он не работает с датой?
Каков наилучший способ добиться эффекта "точка-в-время", который я ищу, без необходимости поддерживать script, который жестко кодирует различные внешние элементы?
Я запускаю систему Linux.
Ответы
Ответ 1
Это неэффективно, поскольку он вызывает обновление svn чаще, чем обычно (обычно). В противном случае, это короткое сладкое:
Unix:
find . -name .svn -execdir svn update -r {2010-08-30} \;
Окна:
forfiles /m .svn /s /c "cmd /c svn up -r {2010-08-30}"
Ответ 2
При использовании svn: externals, как правило, плохой идеей использовать внешний без номера версии. Это означает, что становится сложно сопоставить версию внешнего с версией содержащего проект; Я знаю, что это трудно, от попыток отследить некоторую историю в проекте, содержащем внешние элементы, и я должен был бы угадать, какая версия соответствовала ревизии в содержащем проекте (иногда это было раньше, потому что кто-то обновил внешний проект и затем обновил содержащийся проект, иногда это было позже, потому что кто-то редактировал файлы непосредственно во внешнем контроле, а затем совершил его).
Вместо этого, как это было предложено в окне наконечника, пара абзацев в разделе
Ответ 3
Это является лучшим решением проблемы, которую я нашел на сегодняшний день (это сложная проблема - разработчики деверсий должны исправить это в ядре), Этот пример касается, в частности, mplayer, но вы должны легко видеть логику.
; fetch the rev I want without including the externals
svn checkout -r "$REV" --ignore-externals \
svn://svn.mplayerhq.hu/mplayer/trunk
; grab the date of that rev from the svn info output
DATE=`svn info trunk|sed -n '/^Last Changed Date/s/.*: \(.*\) (.*/\1/p'`
; fetch the externals using that date
svn checkout -r "{$DATE}" \
svn://svn.mplayerhq.hu/ffmpeg/trunk/libavutil \
svn://svn.mplayerhq.hu/ffmpeg/trunk/libavformat \
svn://svn.mplayerhq.hu/ffmpeg/trunk/libavcodec \
svn://svn.mplayerhq.hu/ffmpeg/trunk/libpostproc
Ответ 4
У меня все еще нет идеального решения, но это близко:
svn propget svn:externals | sed -e 's/ .*$//g' | xargs svn up -r'{20090324}'
Это работает в моем случае, потому что нет рекурсивных внешних элементов, и все внешние значения определены без пробелов в каталоге или номере ревизии, поэтому регулярное выражение может легко отрубить конечный путь репозитория.
Я уверен, что существует лучшее регулярное выражение, которое решит проблему в общем случае.
Изменить: На самом деле, чем больше я думаю об этом, тем больше проблем я вижу. Самым большим из них является использование svn: externals из текущей версии, а не svn: externals версии в указанную дату. Это еще сложнее, чем я думал.
Ответ 5
На основании ответа Дэйва Коэна, но довольно быстро:
find . -name '.svn' -execdir svn up --ignore-externals -r '{2014-02-05}' \;
Ответ 6
Это сложно, и я боюсь, что не могу предложить хорошее решение вашей текущей ситуации, но Брайан дал ответ о том, как избежать этого.
Уклонение сводится к немного теории репозитория - в принципе, не должно быть возможности изменить какой-либо исходный код для вашего проекта без соответствующей ревизии, появляющейся в багажнике.
Указывая все внешние элементы на теги или конкретные изменения, никакие изменения из них не могут отображаться в основной истории проекта без внесения изменений во внешнюю ссылку. Но если вы укажете внешний элемент на движущуюся ствол, изменение внешнего не будет отображаться на основной временной шкале проекта, оставив вас в том положении, в котором вы находитесь.
Лично я понял, что внешние ссылки следует рассматривать и выпускать как независимые проекты, поэтому все внешние ссылки указывают на теги. Во время интенсивной параллельной разработки, это прекрасно, чтобы "переключить" внешнее на магистраль или иметь ветвь с нестабильной разработкой, временно указывающую на внешнюю магистраль, но магистральная проектная магистраль всегда указывает на стабильную внешнюю, и это осознанное решение для обновления. Это мнение может быть излишним для вашей ситуации, но стоит посмотреть на другие возможности.
Ответ 7
хорошая утилита, которая будет замораживать внешние данные с учетом пути. мы используем эту утилиту для замораживания внешних элементов после создания тега из туловища:
http://svnxf.codeplex.com/
Ответ 8
Проблема заключается в том, что вы и ваши коллеги не использовали явные номера ревизий с вашими внешними. Вы должны начать сразу!
Интуитивно я мог подумать, что проверка чего-то с определенной даты будет рекурсивно "привязывать" внешний вид к этой дате, даже если внешние ссылки указывают на некоторую ревизию HEAD
. Но, ну, это не так.
Ответ 9
У KSvn может быть эта функция. http://subversion.tigris.org/links.html#desktop-integrations
Ответ 10
Обновление/дата/и т.д., которые вы обновляете основным WC, не передается внешним пользователям при их обновлении. В отсутствие конкретной ревизии, указанной во внешнем определении, они всегда будут отслеживать главу того, на что они указывают. Если вы укажете там ревизию, то это единственная ревизия, которую вы когда-либо получите. Я почти уверен, что вы пытаетесь сделать это невозможно - это подход, который я пытался использовать для решения проблемы, которую я имел, поскольку я описываю в этот вопрос. (Я никогда не решал эту проблему, хотя я думаю, что идея прокси, которая упомянула, что она может это сделать, вероятно, вам это пока не поможет)
Ответ 11
Как недавно у меня возникла аналогичная проблема, я написал немного script для проверки репозитория при конкретной ревизии, а также проверки внешних данных на дату этой ревизии:
https://gist.github.com/3413952
Полезно, если вам нужно найти источник ошибки и хотите иметь что-то похожее на функцию git
bisect.
Ответ 12
Пусть svn выполняет рекурсию для вас.
Tempfile и tee
находятся только здесь, чтобы вы могли видеть полный вывод:
SVN_UP_OUTPUT=$(mktemp SVN_UP_OUTPUT.XXXXX)
svn up -r$REVISION | tee $SVN_UP_OUTPUT
cat $SVN_UP_OUTPUT | egrep '^Fetching external' | egrep -o "'.*'" | sed -e "s/'//g" | while read DIR;do
echo $$ svn up -r$REVISION "$DIR"
svn up -r$REVISION "$DIR"
done
rm $SVN_UP_OUTPUT
Если вы не заботитесь о выходе, его можно сократить до:
svn up -r$REVISION | egrep '^Fetching external' | egrep -o "'.*'" | sed -e "s/'//g" | while read DIR;do
svn up -r$REVISION "$DIR"
done
И, конечно, в вашем случае:
REVISION='{20090324}'