Subversion更新外部日期

时间:2009-03-25 22:12:48

标签: svn

我正在SVN控制下建立一个大型的项目。代码库的许多部分都被检查为外部,但正在被其他人积极处理 我想更新我的整个工作副本,外部和所有,以便它反映了特定时间点的各种存储库的HEAD。我最初的尝试是:

svn up -r'{20090324}'

这会将当前目录更新为指定日期,但会将所有外部更新为当前日期。一次更新一个外部组件按预期工作 我理解,由于外部的性质,单个更新无法使用修订号,但为什么它不适用于日期?
什么是实现我正在寻找的时间点效果的最佳方法,而不必维护一个硬编码各种外部的脚本?

我正在运行Linux系统。

12 个答案:

答案 0 :(得分:38)

这是低效的,因为它比(通常)需要更频繁地调用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}"

答案 1 :(得分:8)

当使用svn:externals时,使用没有修订号的外部通常是个坏主意。这意味着很难将外部版本与包含项目的版本相关联;我知道这很困难,从试图在包含外部的项目中追踪一些历史记录,我将不得不猜测哪个修订版与包含项目中的修订版相对应(有时它更早,因为有人更新了外部项目和然后更新了包含项目,有时后来是因为某人直接在外部签出中编辑了文件然后提交了它。)

相反,正如提示框中提到的externals section in the subversion book中的几个段落一样,您应该始终使用修订号提交外部。这样,每当您签出包含项目的特定修订版时,也会检出外部的相应修订版。它确实意味着更多的工作,因为你必须每次更新svn:externals属性中的修订号(我们编写了一个自动执行的脚本),但从长远来看,这是一个更好的解决方案。

编辑:这是我们使用的脚本的骨架(一个rake任务),用于方便地更新外部并保持所有内容同步。

desc 'Update external for this project (rake update_external r=17789)'
task :update_external do |t|
  rev = ENV['r']
  rev =~ /^\d+$/ or raise "Invalid SVN revision number: r=<#{rev}>"

  # Update the project.
  sh "svn update"

  URL = 'svn+ssh://example.com/external/trunk'
  sh "svn propset svn:externals 'external -r#{rev} #{URL}' containing/directory"

  # Update again -- to put the externals back to the right revision.
  sh "svn update"
end

答案 2 :(得分:3)

This是我发现的问题的最佳解决方案(这是一个棘手的问题 - 颠覆开发者应该将其修复到核心)。这个例子特别涉及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

答案 3 :(得分:2)

我仍然没有一个完美的解决方案,但这个问题很接近:

svn propget svn:externals | sed -e 's/ .*$//g' | xargs svn up -r'{20090324}'

这适用于我的情况,因为没有递归外部,并且所有外部都定义为目录中没有空格或修订号,因此正则表达式可以轻松地删除尾随存储库路径。

我确信有更好的正则表达式可以解决这个问题。

编辑:其实我对此的想法越多,我看到的问题就越多。其中最大的一点是它使用的是当前版本的svn:externals,而不是指定日期版本的svn:externals。这比我原先想象的要复杂得多。

答案 4 :(得分:2)

根据Dave Cohen的回答,但速度要快得多:

find . -name '.svn' -execdir svn up --ignore-externals -r '{2014-02-05}' \;

答案 5 :(得分:1)

这很棘手,我担心我无法为你目前的情况提供一个好的解决方案 - 但Brian已经给出了如何避免它的答案。

避免归结为一些存储库理论 - 基本上,如果没有相应的修订版出现在trunk中,则无法修改项目的任何源代码。

通过将所有外部指向标记或特定修订,如果不对外部引用进行更改,则不会对主项目历史记录中的更改进行更改。但是如果你将一个外部指向一个移动的行李箱,那么对外部的改变根本不会出现在主项目的时间线上 - 让你处于你所处的位置。

就个人而言,我认为外部应该作为独立项目处理和发布,因此所有外部都指向标签。在大量并行开发期间,可以将外部“切换”到主干,或者将不稳定的开发分支临时指向外部主干,但主线项目主干始终指向稳定的外部,并且有意识地决定升级。这种观点对你的情况可能有点过分,但值得看看其他可能性。

答案 6 :(得分:1)

很好的实用程序会冻结外部给定路径。我们在从trunk创建标记后使用此util来冻结外部:

http://svnxf.codeplex.com/

答案 7 :(得分:1)

这里的问题是您和您的同事没有在外部使用明确的修订号。 You should begin at once

直觉上我可能认为从某个特定日期检出某些内容会递归地“固定”该日期的外部查找,即使外部指向某些HEAD修订版也是如此。但是,它没有。

答案 8 :(得分:0)

答案 9 :(得分:0)

您正在更新主WC的修订/日期/等在更新时不会传递到外部。如果没有在外部定义中指定的特定修订版,它们将始终跟踪它们指向的任何内容的头部。如果您在那里指定修订版,那么这是您将获得的唯一修订版。我很确定你要做的事情是不可能的 - 这是我尝试用来解决我遇到的问题的一种方法,正如我在this question中描述的那样。 (我从来没有解决过这个问题,虽然我认为那里提到的代理理念可以做到。但它可能对你没有帮助。)

答案 10 :(得分:0)

由于我最近遇到过类似的问题,我编写了一个小脚本来检查特定修订版本的存储库,同时还检查了修订日期的外部代码: https://gist.github.com/3413952

如果您需要查找错误来源并希望获得与git的bisect功能类似的内容,则非常有用。

答案 11 :(得分:-1)

让svn为你做递归。

临时文件和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}'