如何查看CVS分支点?

发布于 2024-07-24 15:06:36 字数 943 浏览 2 评论 0原文

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

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

有什么办法可以做到这一点吗?

无法从备份恢复到早期的存储库版本。

编辑:我知道我可以通过基于日期的结账来解决这个问题。 我想知道是否仍然可以进行基于标签的操作。

更新(回复@Philip Derbeko):我知道CVS在文件之间不关联。 但 CVS 确实有分支发生位置的信息。 在 ViewVC 中,我什至可以看到它:

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

下一个文件修订版是:

File X - Revision 1.y。 2.1 - 分支:releaseX - CVS 标签:releaseX1

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

First, I have to admit I screwed up a little with CVS. I had a release tag releaseX, which was done some time back (i.e., not HEAD). Then I decided I need a maintenance branch at that point. Instead of creating a branch tag (branchX) in addition to releaseX, I deleted the release tag and created a branch tag (erroneously) named releaseX. I then proceeded to work on that maintenance branch, and created releaseX1, releaseX2 etc.

My problem: when I check out releaseX, I get the branch head, i.e. the latest code from that branch. What I need now is the code at the branch point, i.e. the former releaseX code.

Is there any way to do this?

Reverting to earlier repository version from backup is not an option.

Edit: I know I can work around it by doing a date-based checkout. I would like to know if it's possible to still do a tag-based one.

Update (Re @Philip Derbeko): I know that CVS does not correlate between files. But CVS does have the information where the branch occured. In ViewVC, I can even see it:

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

The next file revision is:

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

The metadata is apparently there. Hence my question: Is it possible to check out the branch point, not the branch HEAD?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

忆离笙 2024-07-31 15:06:36

由于您在分支时没有设置标签,所以我看到的唯一方法是使用日期方法。
但您现在仍然可以设置该标签。 假设您想将该初始版本命名为“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 cvs admin -N cvs admin -N cvs admin -N 旧的>:< 需要使用 new > 。 但无论如何,重命名分支都是一个坏主意。 (我很抱歉首先提出它;-)。),重命名会弄乱其他用户的工作副本。 因此,最好保留原来的名称。

Since you did not set a tag when branching, the only way I see, is to use the date approach.
But you can still set that tag now. Lets assume you want to call that initial release "ReleaseX0", because unfortunately the name "ReleaseX" is already occupied for the branch. Depending on whether you want to set the tag on the branch or on the MAIN branch you can use either of these checkout commands:

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

Then set the tag:

cvs tag releaseX0

From now on you can checkout this release in the same way as you checkout the other releases.


As you pointed out in your comment to my initial response, renaming the branch from releaseX to releaseX_branch like this does not work:

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

To rename a branch cvs admin -N < old >:< new > needs to be used. But renaming a branch is a bad idea anyway. (I am sorry for bringing it up in the first place ;-).), Renaming will mess up the working copies of other users. So it is probably best to stick with the original name.

不打扰别人 2024-07-31 15:06:36

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

我提出的解决方案是找出每个文件的分支点修订号,并通过 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";

This comes four years later - it won't help you out, but it may help someone like myself trying to figure this problem out via google. I recently ran across the same problem with a merge that I am doing. I need to see the parent ancestor of files between the branch head and mainline head - which is the branch point. The branch point was not tagged and was created years ago - at an indeterminate time so tagging by time is no help.

The solution I came up with is figuring out the branch point revision number for each file and applying a branch point tag via a PERL script. It is very similar to what is pointed out here: http://www.cvsnt.org/pipermail/cvsnt/2006-February/024063.html

A little CVS background: In CVS branches are kept track of by adding a .0.x to the mainline revision of the file. For example if the mainline revision is 1.18, then a branch off of that will be 1.18.0.x, X the branch number (if there were already a branch in existence from this revision number then x would be 2 -> 1.18.0.2). The ".0" is dropped when you revise files on the branch so the branch will be 1.18.0.2 in this example and the first revision will be 1.18.2.1 and the second revision will be 1.18.2.2. A lot of this is drawn from this: http://www.astro.princeton.edu/~rhl/cvs-branches.html#branchnumbers

I found a perl script here: https://github.com/effectiveprogramming/ep-cvs/wiki/List-CVS-Tags that will either list the CVS tags when given the -t switch or if given a branch name tag it will list all files and revision associated with that tag. This script uses this command: "cvs -q status -R -v filename" which will list the branches with the ".0" part hidden, so you simply remove the ".x" from the revision number of the desired branch name. So I took the script on github and added a few lines. You simply execute this script with a branch name as an argument and it will tag the branch point with the same branch name with an _BP appended to it.

#!/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";
九公里浅绿 2024-07-31 15:06:36

我不是 CVS 专家。 如果我处于你的位置,我会这么做。 CVS 将 HEAD 分支中的文件版本标记为 1.N ,当您在版本 X 分支文件时,提交到该分支的内容将被标记为 1.XBM 。 因此,在查看 releaseX 后,我会编写一个脚本,将分支中更改的文件更新为版本 1.X,然后标记我的工作副本。 也许有更简单的方法,但我不知道。

I'm not a CVS expert. Here's what I would do if I were in your place. CVS marks file versions in HEAD branch as 1.N, when you branch file at version X, commits to that branch get marked as 1.X.B.M . So after checking out releaseX, I would write a script that would update files that were changed in branch to a version 1.X, and then tag my working copy. Maybe there is a simpler way, but I don't know about it.

不即不离 2024-07-31 15:06:36

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

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

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

Sorry, can't be done.
The only option you have is doing time-based checkout.
The problem is that CVS does not correlated between different files, which is done using tags. Once the tag is gone, the information that ties different files together is gone forever. Meaning that you have to write a script finding the branch point for every file.

As a general practice and in case you don't care for many tags in repository, I would suggest to create a tag on the trunk (or a branch from where you are branching) and on merge as well. Those tags should follow naming convention and then in CVS scripts you can prevent messing with them.

With CVS you should automate as much as possible :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文