代码之家  ›  专栏  ›  技术社区  ›  Whatsit

Subversion将外部更新为日期

svn
  •  39
  • Whatsit  · 技术社区  · 16 年前

    我正在SVN控制下的一个大型、已建立的项目中工作。代码库的许多部分作为外部代码被签出,但其他人正在积极地进行工作。
    我想更新我的整个工作副本、外部版本和所有版本,以便在特定的时间点上反映出各种存储库的头部。我最初的尝试是:

    svn up -r'{20090324}'
    

    这会将当前目录更新到指定的日期,但会将所有外部目录更新到 现在的 日期。一次更新一个外部对象可以按预期工作。
    我理解,由于外部特性,单个更新无法使用修订号,但为什么它不能使用日期?
    在不需要维护硬编码各种外部内容的脚本的情况下,实现我正在寻找的时间点效果的最佳方法是什么?

    我在运行Linux系统。

    12 回复  |  直到 10 年前
        1
  •  38
  •   jarlh    10 年前

    这是低效的,因为它调用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
  •  8
  •   Pål Brattberg    13 年前

    使用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
    
        3
  •  3
  •   Artem Russakovskii    16 年前

    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
    
        4
  •  2
  •   Whatsit    16 年前

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

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

    在我的例子中,这是可行的,因为没有递归外部变量,并且所有外部变量都定义为目录中没有空格或修订号,所以正则表达式可以很容易地切断后面的存储库路径。

    不过,我相信有更好的regex可以一般地解决这个问题。

    编辑:事实上,我想得越多,我看到的问题就越多。其中最大的一个是它使用的是svn:externals 现在的 版本,而不是指定日期版本的svn:externals。这比我最初想象的还要复杂。

        5
  •  2
  •   maniek    11 年前

    根据戴夫·科恩的回答,但速度要快得多:

    find . -name '.svn' -execdir svn up --ignore-externals -r '{2014-02-05}' \;
    
        6
  •  1
  •   Jim T    16 年前

    这很棘手,恐怕我不能为你目前的处境提供一个好的解决方案——但是布莱恩已经给出了如何避免这种情况的答案。

    这种避免归结于一点知识库理论——基本上,如果没有在主干中出现相应的修改,就不可能修改项目的任何源代码。

    通过将所有外部对象指向标记或特定修订,在不向外部引用提交更改的情况下,它们的任何更改都不会显示在主项目历史记录中。但是,如果你将一个外部指向一个移动的主干,那么对外部的更改就不会出现在主项目的时间轴上——让你处于你所处的位置。

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

        7
  •  1
  •   dnndeveloper    15 年前

    很好的实用程序,可以冻结给定路径的外部。我们使用此实用程序在从主干创建标记后冻结外部:

    http://svnxf.codeplex.com/

        8
  •  1
  •   Lightness Races in Orbit    12 年前

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

    直观地说,我可能认为从某个特定日期签出某些内容会递归地“绑定”外部对象查找该日期,即使外部对象指向某个日期 HEAD 修订。但事实并非如此。

        9
  •  0
  •   Jonathan Parker    16 年前
        10
  •  0
  •   Community CDub    8 年前

    您要将主wc更新为的修订/日期等在更新时不会传递给外部。在没有外部定义中指定的特定修订的情况下,它们将始终跟踪它们指向的任何对象的头部。如果您在那里指定了修订,那么这是您将得到的唯一修订。我很确定你想做的事情是不可能的——正如我在书中所描述的,这是我试图用来解决我遇到的问题的一种方法。 this question .(我从来没有解决过这个问题,尽管我认为上面提到的代理思想可以解决这个问题。但这可能对你没有帮助)

        11
  •  0
  •   Orangenhain    13 年前

    正如我最近遇到的一个类似的问题,我编写了一个小脚本来在特定的版本中签出存储库,同时在该版本的日期签出外部代码: https://gist.github.com/3413952

    如果您需要找到bug的来源,并希望有类似的 git 的对分特征。

        12
  •  -1
  •   Izkata    12 年前

    让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}'