Next: , Previous: Avoiding Option Fatigue, Up: Other Useful CVS Commands


Getting Snapshots (Dates And Tagging)

Let's return to the example of the program that's in a broken state when a bug report comes in. The developer suddenly needs access to the entire project as it was at the time of the last release, even though many files may have been changed since then, and each file's revision number differs from the others. It would be far too time-consuming to look over the log messages, figure out what each file's individual revision number was at the time of release, and then run update (specifying a revision number with -r) on each one of them. In medium- to large-sized projects (tens to hundreds of files), such a process would be too unwieldy to attempt.

CVS, therefore, provides a way to retrieve previous revisions of the files in a project en masse. In fact, it provides two ways: by date, which selects the revisions based on the time that they were committed, and by tag, which retrieves a previously marked "snapshot" of the project.

Which method you use depends on the situation. The date-based retrievals are done by passing update the -D flag, which is similar to -r but takes dates instead of revision numbers:

     floss$ cvs -q update -D "1999-04-19"
     U hello.c
     U a-subdir/subsubdir/fish.c
     U b-subdir/random.c
     floss$

With the -D option, update retrieves the highest revision of each file as of the given date, and it will revert the files in the working copy to prior revisions if necessary.

When you give the date, you can, and often should, include the time. For example, the previous command ended up retrieving revision 1.1 of everything (only three files showed changes, because all of the others are still at revision 1.1 anyway). Here's the status of hello.c to prove it:

     floss$ cvs -Q status hello.c
     ===================================================================
     File: hello.c                 Status: Up-to-date
        Working revision:          1.1.1.1 Sat Apr 24 22:45:03 1999
        Repository revision:       1.1.1.1 /usr/local/cvs/myproj/hello.c,v
        Sticky Date:               99.04.19.05.00.00
     floss$

But a glance back at the log messages from earlier in this chapter shows that revision 1.2 of hello.c was definitely committed on April 19, 1999. So why did we now get revision 1.1 instead of 1.2?

The problem is that the date "1999-04-19" was interpreted as meaning "the midnight that begins 1999-04-19" – that is, the very first instant on that date. This is probably not what you want. The 1.2 commit took place later in the day. By qualifying the date more precisely, we can retrieve revision 1.2:

     floss$ cvs -q update -D "1999-04-19 23:59:59"
     U hello.c
     U a-subdir/subsubdir/fish.c
     U b-subdir/random.c
     floss$ cvs status hello.c
     ===================================================================
     File: hello.c                 Status: Locally Modified
        Working revision:  1.2     Sat Apr 24 22:45:22 1999
        Repository revision:       1.2     /usr/local/cvs/myproj/hello.c,v
        Sticky Tag:                (none)
        Sticky Date:               99.04.20.04.59.59
        Sticky Options:    (none)
     floss$

We're almost there. If you look closely at the date/time on the Sticky Date line, it seems to indicate 4:59:59 A.M., not 11:59 as the command requested (later we'll get to what the "sticky" means). As you may have guessed, the discrepancy is due to the difference between local time and Universal Coordinated Time (also known as "Greenwich mean time"). The repository always stores dates in Universal Time, but CVS on the client side usually assumes the local system time zone. In the case of -D, this is rather unfortunate because you're probably most interested in comparing against the repository time and don't care about the local system's idea of time. You can get around this by specifying the GMT zone in the command:

     floss$ cvs -q update -D "1999-04-19 23:59:59 GMT"
     U hello.c
     floss$ cvs -q status hello.c
     ===================================================================
     File: hello.c                 Status: Up-to-date
        Working revision:  1.2     Sun Apr 25 22:38:53 1999
        Repository revision:       1.2     /usr/local/cvs/myproj/hello.c,v
        Sticky Tag:                (none)
        Sticky Date:               99.04.19.23.59.59
        Sticky Options:    (none)
     floss$

There – that brought the working copy back to the final commits from April 19 (unless there were any commits during the last second of the day, which there weren't).

What happens now if you run update?

     floss$ cvs update
     cvs update: Updating .
     cvs update: Updating a-subdir
     cvs update: Updating a-subdir/subsubdir
     cvs update: Updating b-subdir
     floss$

Nothing happens at all. But you know that there are more recent versions of at least three files. Why aren't these included in your working copy?

That's where the "sticky" comes in. Updating ("downdating"?) with the -D flag causes the working copy to be restricted permanently to that date or before. In CVS terminology, the working copy has a "sticky date" set. Once a working copy has acquired a sticky property, it stays sticky until told otherwise. Therefore, subsequent updates will not automatically retrieve the most recent revision. Instead, they'll stay restricted to the sticky date. Stickiness can be revealed by running cvs status or by directly examining the CVS/Entries file:

     floss$ cvs -q update -D "1999-04-19 23:59:59 GMT"
     U hello.c
     floss$ cat CVS/Entries
     D/a-subdir////
     D/b-subdir////
     D/c-subdir////
     /README.txt/1.1.1.1/Sun Apr 18 18:18:22 1999//D99.04.19.23.59.59
     /hello.c/1.2/Sun Apr 25 23:07:29 1999//D99.04.19.23.59.59
     floss$

If you were to modify hello.c and then try to commit

     floss$ cvs update
     M hello.c
     floss$ cvs ci -m "trying to change the past"
     cvs commit: cannot commit with sticky date for file 'hello.c'
     cvs [commit aborted]: correct above errors first!
     floss$

CVS would not permit the commit to happen because that would be like allowing you to go back and change the past. CVS is all about record keeping and, therefore, will not allow you to do that.

This does not mean CVS is unaware of all the revisions that have been committed since that date, however. You can still compare the sticky-dated working copy against other revisions, including future ones:

     floss$ cvs -q diff -c -r 1.5 hello.c
     Index: hello.c
     ===================================================================
     RCS file: /usr/local/cvs/myproj/hello.c,v
     retrieving revision 1.5
     diff -c -r1.5 hello.c
     *** hello.c   1999/04/24 22:09:27     1.5
     --- hello.c   1999/04/25 00:08:44
     ***************
     *** 3,9 ****
       void
       main ()
       {
         printf ("Hello, world!\n");
     -   printf ("between hello and goodbye\n");
         printf ("Goodbye, world!\n");
       }
     --- 3,9 --
       void
       main ()
       {
     +   /* this line was added to a downdated working copy */
         printf ("Hello, world!\n");
         printf ("Goodbye, world!\n");
       }

This diff reveals that, as of April 19, 1999, the between hello and goodbye line had not yet been added. It also shows the modification that we made to the working copy (adding the comment shown in the preceding code snippet).

You can remove a sticky date (or any sticky property) by updating with the -A flag (-A stands for "reset", don't ask me why), which brings the working copy back to the most recent revisions:

     floss$ cvs -q update -A
     U hello.c
     floss$ cvs status hello.c
     ===================================================================
     File: hello.c                 Status: Up-to-date
        Working revision:  1.5     Sun Apr 25 22:50:27 1999
        Repository revision:       1.5     /usr/local/cvs/myproj/hello.c,v
        Sticky Tag:                (none)
        Sticky Date:               (none)
        Sticky Options:    (none)
     floss$
Karl Fogel wrote this book. Buy a printed copy via his homepage at red-bean.com

copyright  ©  January 18 2019 sean dreilinger url: https://durak.org/sean/pubs/software/cvsbook/Getting-Snapshots-_0028Dates-And-Tagging_0029.html