Обновление субверсии на дату

Я работаю над большим, установленным проектом под управлением 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. Но, ну, это не так.

Ответ 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}'