【问题标题】:cvs to mercurial conversion gets tags wrongcvs 到 mercurial 的转换得到标签错误
【发布时间】:2010-04-02 17:21:41
【问题描述】:

我已经尝试了所有recommended conversion techniques

他们大多设法正确获取最新版本的文件,但每一个都会破坏我的历史记录。当我运行“hg up $tag”时,我的 cvs 项目中的许多(大多数?)标签至少有一个文件错误

我的 cvs 存储库并没有那么复杂。为什么不能转换它? 我想转储 cvs 并转换为 mercurial,但并非没有历史记录。

回顾一下我的挫败感:

我试过 hg 转换 (试过--branchsort,--timesort, fuzz=0)

我尝试了 cvs2svn 然后 hg 转换。

tailor 不适用于最新版本的 mercurial

fromcvs从地球表面消失

hg-cvs-import 已废弃 4 年,不适用于 hg 的最新版本

我尝试过使用 mercurial 的两个最新版本(1.5 和 1.5.1)。

【问题讨论】:

  • 当你做 cvs2svn 时,svn repo 看起来还好吗?
  • 我相信是的。我对颠覆的(非)标签实现的无知有些限制。一些抽查表明 tags/$TAG 目录与 cvs up -Ad -r $TAG 的结果一致。
  • 我认为问题与文件的时间线按时间顺序排列的标签有关。例如说在制作标签 v250 时文件 foo.cc 的 HEAD 版本还没有准备好,所以我通过 'cvs up -r' 提取并标记了旧版本的 foo.cc cvsps 似乎有很多麻烦

标签: mercurial cvs tags


【解决方案1】:

马克,这是一个次优的解决方案,但是当我所在的一家公司进行 CVS->Mercurial 迁移时,我们认为我们只关心标签快照,因此我们构建了一个类似的 for 循环:

for thetag in $(cat LIST_OF_RELEASE_TAGS) ; do
   cvs update -r $thetag
   hg commit --addremove -m "snapshot $thetag" -u "import"
   hg tag $thetag
done

这假设了一个线性的标签链,但我们只拉入了主/生产分支。一个更复杂的循环会在每次提交之前调用“hg update”来获取反映 CVS 分支的父级。

这绝对不是“完整的历史”,但这足以让我们对继续使用 Mercurial 感到满意,而不会失去说“1.1.11 版本到底是什么?!”的能力。我们总是可以回到 cvs 是需要cvs blame 级别历史记录。

【讨论】:

    【解决方案2】:

    fromcvs 回来了。我正在我们的一个非常大的 repo 上对其进行测试,它非常快并且可以处理增量转换。

    【讨论】:

      【解决方案3】:

      我找到了各种各样的解决方案。我对此并不感到兴奋,但现在必须这样做。 我能够检测到导致问题的标签并从转换中忽略这些标签。缺少标签比错误标签好得多(假设原始 cvs 存储库被保留以供备份)

      警告:以下假设您已经制作了 CVSROOT 的副本,并且正在努力。不要乱用你的原件。

      这是一个适用于我的 linux 机器的 bash 解决方案。它可能会烧毁你的房子,并邀请你的小学恶霸搬到你隔壁。您已收到警告。

      它使用 cvsps 来识别问题标签,使用 rcs 来删除它们,然后从 CVSROOT/history 中删除标签。删除 cvsps 缓存后,hg 转换按预期工作。

      CVSROOT=/path/to/your/copy
      MODULE=cvsmodule
      rm -rf ~/.cvsps ~/.hg.cvsps # this cache is EVIL!
      
      BADTAGS="`cvsps -q -x $MODULE |grep Tag: |grep -e FUNKY -e INVALID | awk '{print $2}' `"
      while [ ! -z "$BADTAGS" ];do
          cd $CVSROOT/$MODULE
          for badtag in $BADTAGS;do
            echo removing tag $badtag
            grep -lr $badtag . | xargs --no-run-if-empty -l1 rcs -q -n$badtag
            grep -v "$badtag|$MODULE" < $CVSROOT/CVSROOT/history > $CVSROOT/CVSROOT/history_
            mv $CVSROOT/CVSROOT/history_  $CVSROOT/CVSROOT/history
          done
          BADTAGS="`cvsps -q -x $MODULE |grep Tag: |grep -e FUNKY -e INVALID | awk '{print $2}' `"
      done
      rm -rf ~/.cvsps ~/.hg.cvsps # this cache is EVIL!
      mkdir ~/hgcvt
      cd ~/hgcvt
      cvs co $MODULE
      hg convert $MODULE
      

      【讨论】:

      • 在 hg 中拥有所有内容后,您可以随时重新标记丢失的标签吗?
      • 您可以使用“rtag -d”来通过 CVS 删除标签,而不是调用 RCS。确实是等效的,但是直接进入 RCS 并操作 .v 文件感觉不对。
      【解决方案4】:

      我现在意识到 cvs 标签和 hg 标签之间存在某些基本的不兼容性。

      在 cvs 中,文件的一个版本具有与其不同版本相关联的标签。

      在 hg 中,版本是变更集的别名。换句话说,工作文件在某个时间快照的状态

      区别很微妙,但很重要。

      可以在 cvs 中对不代表时间快照的版本进行标记发布。这在 hg 中是不可能的。

      当然可以应用补丁来获取副本。然而,这会在存储库上创建很多新的负责人,而没有什么好处(假设 cvs 存储库仍然保留给后代)。

      恐怕从 cvs 到 mercurial 的完美转换是不切实际的。 Ry4an 的解决方案适用于那些只关心重新创建版本的人。我对源文件的历史和演变更感兴趣。

      我编写了以下脚本,以便在转换之前简单地删除 $CVSROOT 中的所有 cvs 标签。例如标签“v321”变成“v321_prehg”。这样开发人员就会知道这些标签是非权威的,他们必须回到只读的 cvs 树。

      #!/usr/bin/python
      import os
      import sys
      import stat
      
      def die(msg):
          sys.stderr.write(msg)
          sys.exit(1)
      
      cvsroot =os.getenv("CVSROOT")
      if cvsroot is None:
          die("CVSROOT not defined" )
      
      print "CVSROOT=%s" % cvsroot
      
      for rcsfile in os.popen("find %s -name '*,v'" % cvsroot).xreadlines():
          rcsfile = rcsfile.replace('\n','')
          print "rcsfile:%s" % rcsfile
          st=os.stat(rcsfile)
          if  st.st_mode & stat.S_IWUSR == 0:
              os.chmod(rcsfile,st.st_mode | stat.S_IWUSR)
      
          f = open(rcsfile,"r")
          inlines=f.readlines()
          f.close()
      
          outlines=[]
          insymbols=False
          symbolsDone=False
          for l in inlines:
              if insymbols and not symbolsDone:
                  if l.find('\t') == 0:#tag line
                      l= l.replace(":","_prehg:",1)
                  else:
                      symbolsDone=True
              else:
                  if l == "symbols\n":
                      insymbols=True
              outlines.append(l)
      
          f = open(rcsfile,"w")
          f.writelines( outlines )
          f.close()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-11
        相关资源
        最近更新 更多