How do I revert a big change in CVS?

前端 未结 10 536
离开以前
离开以前 2021-02-01 16:49

One of my colleagues has totally messed up the contents of a directory in our main CVS repository. I need to just revert the whole module to the state it was in at the end of l

相关标签:
10条回答
  • 2021-02-01 17:06

    If you or a colleague are comfortable with git, you could use git cvsimport to create a git repository mirroring the CVS repository. Reverting a commit/changeset in git is trivial (using git revert). You could then use git cvsexportcommit to send the revert commit to CVS.

    This might all sound overly complicated, but in my experience git cvsimport and git cvsexportcommit work really well once you've got everything set up. You end up with all the power of git personally even though the project is still using CVS.

    0 讨论(0)
  • 2021-02-01 17:07

    If you have a backup of your repository (the actual RCS files on the server, e.g. on tape) you could just restore that folder on the CVS server to the state it was before. Don't forget to stop the CVS server before doing this (and restart it afterwards).

    0 讨论(0)
  • 2021-02-01 17:10

    I'm still interested to know if there's an easier way. (There must surely be an easier way). What I ended up doing was, on a Linux PC using bash:

    # Get woking copy we're going to change
    cd ~/work
    rm -rf modulename
    cvs up -dP modulename
    cd modulename
    
    # Remove all files
    find . -name CVS -prune -o -type f -print | xargs cvs rm -f
    
    # Get the old revision
    cd ~
    mkdir scratch
    cd scratch
    cvs -q co -D 2008-12-31 modulename
    cd modulename
    
    # Copy everything to the working dir and do "cvs add" on it
    find . -name CVS -prune -o -type f -print | \
        xargs tar c | \
        (cd ~/work/modulename && tar xv | \
        xargs cvs add)
    
    # Check everything is OK before we commit
    cd ~/work/modulename
    cvs -nq up
    
    # it gave me an error on readme.txt because I'd deleted and then added it, so:
    mv readme.txt x # save good rev
    cvs add readme.txt # resurrect the bad rev
    mv x readme.txt # clobber file with good rev
    
    # Commit it
    cvs commit -m "Revert all changes this year"
    
    # Delete now-empty directories
    cvs -q up -dP
    
    # Double-check everything is back how it was
    diff -ur -xCVS ~/scratch/modulename ~/work/modulename
    

    Then I discovered that there were still differences - my colleague had added filenames containing spaces, which weren't deleted by the above process. I had to delete those separately. (I should have used find ... -print0 rather than -print, and passed the -0 argument to xargs. I just didn't realise there were files with spaces.)

    0 讨论(0)
  • 2021-02-01 17:12

    There are several problems with CVS and you're hitting them with such a problem.

    1. CVS is file-oriented, no concept of a changeset or snasphot. That means that changes such as the one you want to revert are a bit difficult to handle. Commits are atomic within a given directory, not outside.

    2. Directories are not versioned. That means that empty directories will be deleted (if you update with -P) and that you have to specify -d to create them on checkout/update.

    So, to answer your question, dates are probably the only way to deal with because you didn't use tags to create some poor man's version of changeset.

    My comment about backups is that it may be easier to recover the whole repo from backups than try to correct things that CVS is not really good at.

    I would encourage you -- but that is another subject -- to change version control as soon as you can. Trust me, I've been dealing with CVS for a long time within the FreeBSD project and learn very quickly how hateful CVS is... See here for some of my views on version control software.

    0 讨论(0)
  • 2021-02-01 17:15

    Actually your initial approach was very close to the solution. The problem is, that joining date-based does not handle removed files and directories correctly. You need to set a tag to the code base you want to join first:

    mkdir code_base1 && cd code_base1
    cvs co -D "2008-12-30" modulename
    cvs tag code_base_2008_12_30
    

    Now do the join tag-based, subtracting all changes between now and 2008-12-30:

    cd .. && mkdir code_base2 && cd code_base2
    cvs co modulename
    cvs update -d -j HEAD -j code_base_2008_12_30  # use -d to resurrect deleted directories
    

    Compare the contents of code_base1 and code_base2. They should be identical except for the CVS meta information. Finally commit the code as it was on 2008-12-30 as new HEAD:

    cvs commit -m "Revert all changes this year"
    

    Note that tagging the code you wish to join like this will not work, because rtag also does not handle removed files and directories correctly, when using -D:

    cvs rtag -D "2008-12-30" code_base_2008_12_30 modulename
    
    0 讨论(0)
  • 2021-02-01 17:16

    Have you tried using the -d option? (build subdirectories)

    As far as I can remember, it's implied for cvs co, but not for cvs up.

    0 讨论(0)
提交回复
热议问题