如何查看CVS分支点?

时间:2009-06-23 07:51:57

标签: cvs

首先,我不得不承认我与CVS搞砸了一下。我有一个发布标签releaseX,这是在一段时间后完成的(即,不是HEAD)。然后我决定在那时我需要一个维护分支。我没有在添加中创建分支标记(branchX)到releaseX,而是删除发布标记并创建了一个名为(错误地)命名的分支标记releaseX。然后我继续处理该维护分支,并创建了releaseX1releaseX2等。

我的问题:当我查看releaseX时,我会得到分支头,即该分支的最新代码。我现在需要的是分支点的代码,即以前的 releaseX代码。

有没有办法做到这一点?

从备份恢复到早期存储库版本不是一种选择。

编辑:我知道我可以通过基于日期的结帐来解决这个问题。我想知道是否仍然可以使用基于标签的那个。

更新(Re @Philip Derbeko):我知道CVS与文件之间没有关联。但CVS 确实具有分支发生的信息。在ViewVC中,我甚至可以看到它:

File X - Revision 1.y - Branch: MAIN - Branch point for: releaseX

下一个文件修订版是:

File X - Revision 1.y.2.1 - Branch: releaseX - CVS Tags: releaseX1

元数据显然存在。因此我的问题是:是否可以查看分支,而不是分支 HEAD

4 个答案:

答案 0 :(得分:9)

由于您在分支时没有设置标记,我看到的唯一方法是使用日期方法。 但是你现在仍然可以设置该标签。让我们假设您要调用该初始版本“ReleaseX0”,因为不幸的是,分支已经占用了名称“ReleaseX”。根据您是要在分支上还是在MAIN分支上设置标记,您可以使用以下任一检查命令:

cvs co -r releaseX -D "2008-12-30" modulename
cvs co -D "2008-12-30" modulename

然后设置标签:

cvs tag releaseX0

从现在开始,您可以像查看其他版本一样查看此版本。


正如您在对我的初步回复的评论中指出的那样,将分支从releaseX重命名为releaseX_branch,就像这样不起作用

cvs rtag -r releaseX releaseX_branch modulename
cvs rtag -d releaseX modulename

重命名分支“cvs admin -N< old>:< new>”需要使用。但无论如何,重命名分支是一个坏主意。 (我很抱歉首先提出它;-)。),重命名会弄乱其他用户的工作副本。所以最好坚持使用原来的名字。

答案 1 :(得分:4)

这是四年之后 - 它不会帮助你,但它可能会帮助像我这样的人试图通过谷歌解决这个问题。我最近遇到了与我正在进行的合并相同的问题。我需要在分支头和主线头之间看到文件的父祖先 - 这是分支点。分支点没有被标记,并且是在几年前创建的 - 在一个不确定的时间,所以按时间标记是没有用的。

我想出的解决方案是找出每个文件的分支点修订号,并通过PERL脚本应用分支点标记。它与此处指出的非常类似:http://www.cvsnt.org/pipermail/cvsnt/2006-February/024063.html

一点CVS背景:在CVS中,通过将.0.x添加到文件的主线修订版来跟踪分支。例如,如果主线修订版是1.18,那么其分支将是1.18.0.x,X是分支编号(如果已经存在来自该修订版编号的分支则x将是2 - > 1.18。 0.2)。修改分支上的文件时会删除“.0”,因此在此示例中分支将为1.18.0.2,第一个修订版将为1.18.2.1,第二个修订版将为1.18.2.2。其中很多内容来自:http://www.astro.princeton.edu/~rhl/cvs-branches.html#branchnumbers

我在这里找到了一个perl脚本:https://github.com/effectiveprogramming/ep-cvs/wiki/List-CVS-Tags将在给定-t开关时列出CVS标记,或者如果给定分支名称标记,它将列出与该标记关联的所有文件和修订。此脚本使用此命令:“cvs -q status -R -v filename”,它将列出隐藏“.0”部分的分支,因此您只需从所需分支名称的修订号中删除“.x”。所以我把这个脚本放在github上并添加了几行。您只需使用分支名称作为参数执行此脚本,它将使用相同的分支名称标记分支点,并附加_BP。

#!/usr/bin/perl

# Simple perl script.  Given a branch name, determine 
# the file revision a branch was created on for all 
# files in a repository and tag those files with a user defined tag.    
# Created 2013/04/05 CPG
# $Id: lstag,v 1.1 2002/09/26 10:02:53 ec Exp $

use strict;

$::VERSION = "1.0";
$::cvs_ID = '$Id: lstag,v 1.1 2002/09/26 10:02:53 ec Exp $'; #'

undef ($::repo);
# Try #1 to get CVS repository location
if (-r "CVS/Root") {
    open (INF, "<CVS/Root") || die "Failed to read CVS/Root file!\n";
    ###chop ($::repo = <INF>);
    $::repo = <INF>;
    close (INF);
} else {
    # Try #2 to get CVS repository location
    if (!$::ENV{"CVSROOT"}) {
        print "CVSROOT environment variable not found!\n";
        print "CVS not detected...\n";
        exit (10);
    }
}
$::repo =~ s/\n$//g;
$::repo =~ s/\r$//g;
($::repo) = $::repo =~ /([^:]+)$/;
$::repo =~ s/\/*$/\//;

### print "CVS repository at $::repo\n";


# Check commandline arguments
if ($#ARGV < 0) {
    print "Missing argument!\n";
    print "Usage: $0 [ tag]\n\n";
    print "Where: tag is number of "; 
    print "     each file this tag was created.\n";
    print "       tag   shows list of files with this tag\n";
    print "\n";
    exit (1);
}

# Get desired tagname
$::tag = $ARGV[0];
$::taglist = 0;
if ($::tag eq "-l") {
    $::taglist = 1;
}



# Run cvs status and catch output
open (INF, "cvs -q status -R -v |") || die "Failed to run cvs status command!\n";
chop (@::STATUS = <INF>);
close (INF);

# Parse status
$::state = 0;
$::fpath = $::frpath = $::fname = $::fstatus = $::ftag = $::ftagrev = "!UNINITIALIZED VARIABLE!";
undef (%::TAGS);
$::found = 0;
for $::lc (0 .. $#::STATUS) {
    $_ = $::STATUS[$::lc];
    if ($::state == 0) {
        if (/^File:/) {
            ($::fname, $::fstatus) = /^File:\s+(\S+\s*\S+)\s+Status:\s+(\S+)/;
            $::state = 1;
        }
        next;
    }
    if ($::state == 1) {
        if (/^\s+Repository revision:/) {
            ($::frpath) = /(\/.*),v/;
            ($::fpath) = $::frpath =~ /^$::repo(.*)$/;
            push @::INFOL, ( $::fpath );
            $::current = $::fpath;
            $::INFO{$::current}->{"rpath"}  = $::frpath;
            $::INFO{$::current}->{"name"}   = $::fname;
            $::INFO{$::current}->{"status"} = $::fstatus;
            $::fpath = $::frpath = $::fname = $::fstatus = "!UNINITIALIZED VARIABLE!";
            $::state = 2;
        }
        next;
    }
    if ($::state == 2) {
        if (/^\s+Existing Tags:/) {
            $::state = 3;
        }
        next;
    }
    if (/^\s+\S+\s+\([^:]+:/) {
        ($::ftag, $::ftagrev) = /^\s+(\S+)\s+\([^:]+:\s+([^\)]+)\)/;
        if ($::taglist) {
            $::TAGL{$::ftag}++;
        }
        if ($::ftag eq $::tag) {
            $::found++;
            $::INFO{$::current}->{"tag"} = $::ftag;
            $::INFO{$::current}->{"tagrev"} = $::ftagrev;
            $::ftag = $::ftagrev = "!UNINITIALIZED VARIABLE!";
        }
    } else { $::state = 0; }
}

# Print results
print "$0 - CVS tag and file lister version $::VERSION\n";
print "ID: $::cvs_ID\n\n";
if ($::taglist) {
    print "List of all known tags:\n\n";
    foreach $::key (sort {uc($a) cmp uc($b)} keys %::TAGL) {
        print "$::key\n";
    }
} else {
    print "Files with tag \"$::tag\":";
    if ($::found > 0) {
        print "\n\n";
    } else {
        print "  NONE\n";
    }
    for $::i (0 .. $#::INFOL) {
        if (!defined($::INFO{$::INFOL[$::i]}->{"tag"})) {
            next;
        }
        $::name = $::INFOL[$::i];
        $::status = $::INFO{$::name}->{"status"};
        $::tagrev = $::INFO{$::name}->{"tagrev"};

        #  Code added to apply a tag to a branch point:
        # regex to strip from last '.' to end of revision #.
        $::ge = '\.[^\.]*$';

        $::branchPtRev = $::tagrev;
        $_ = $::branchPtRev;
        s/$::ge//;
        $::cmd = "cvs tag -r".$_." ".$::tag."_BP " . $::name . " xst";

        #printf "%10s %s\n", ($_, $::name);

        #  printf "%10s %10s\n", ($::branchPtRev, $_);

        #printf $::cmd;
        #  printf "\n";

        # Run cvs command
        open (INF, $::cmd) || die "Failed to run cvs status command!\n";
        close (INF);
    }
}

print "Script Completed Successfully\n";

答案 2 :(得分:2)

我不是CVS专家。如果我在你的位置,我会怎么做。 CVS将HEAD分支中的文件版本标记为1.N,当您在版本X分支文件时,提交到该分支的标记为1.X.B.M。在签出 releaseX 之后,我会编写一个脚本,将分支中更改的文件更新为版本1.X,然后标记我的工作副本。也许有一种更简单的方法,但我不知道。

答案 3 :(得分:1)

抱歉,无法完成。 您唯一的选择是进行基于时间的结账。 问题是CVS在不同文件之间没有相关性,这是使用标签完成的。标签消失后,将不同文件绑定在一起的信息将永远消失。这意味着您必须编写一个脚本来查找每个文件的分支点。

作为一般做法,如果您不关心存储库中的许多标记,我建议在主干(或分支的分支)上创建一个标记,并在合并时。这些标签应该遵循命名约定,然后在CVS脚本中可以防止弄乱它们。

使用CVS,您应尽可能自动化:)