首先,我不得不承认我与CVS搞砸了一下。我有一个发布标签releaseX
,这是在一段时间后完成的(即,不是HEAD)。然后我决定在那时我需要一个维护分支。我没有在添加中创建分支标记(branchX
)到releaseX
,而是删除发布标记并创建了一个名为(错误地)命名的分支标记releaseX
。然后我继续处理该维护分支,并创建了releaseX1
,releaseX2
等。
我的问题:当我查看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 ?
答案 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,您应尽可能自动化:)