by Angie Byron on June 13, 2007 // Short URL

CVS Annotate, or "What the heck were they thinking?"

CVS Annotate? What's this, then?

Ever wanted to get into a developer's head, to figure out why they made a certain change to the code? Ever tracked down a particularly pesky bug, and want to know where point that look of scorn? If so, the cvs annotate command is just what you've been looking for!

The cvs annotate command (and its sister, svn blame) is the "tattle-tale" of the development world. For every single line of code in a file, it will tell you:

  • Who was the last person who touched it?
  • What date was it last changed?
  • In what precise version of the file was it last changed?

Like so:

1.85         (dries    22-Jun-05): require_once './includes/';
1.86         (dries    23-Jul-05): drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
1.67         (dries    28-Sep-03):
1.83         (dries    24-Apr-05): $return = menu_execute_active_handler();
1.91         (unconed  12-Dec-06):

Sound handy? It sure is! And you don't even need to be a command-line geek to benefit!

For example...

Right now, Drupal 6.x-dev spits out a fatal error if the database connection fails:

Fatal error: Call to undefined function file_directory_path() in /Applications/MAMP/htdocs/head/includes/ on line 1769

Darn you, line 1769! Why must you mock me so?!

So I know this had to be introduced at some point relatively recently, since in 5.x, this would give me a nice "Could not connect to database" message, themed with the lovely, smiling Druplicon. Let's take a closer look.

CVS annotate - command-line version

Bring up a command prompt and punch in the following:

$ cvs annotate includes/ > blame.txt
$ vim blame.txt # or pico, if you're like a total wuss. ;)

I redirect this to a file because this sucker is loonnng.

If I head down to line 1769, I see:

1.649        (unconed  01-Jun-07):   $directory = file_directory_path();

Ah-HA! So now I can blame Steven. ;) Let's see what was actually done during that commit:

$ cvs log -r1.649 -N includes/

(-r1.649 limits the list of log messages to only that revision, and -N stops it from printing a huge list of tags. See the manual for additional cvs log options.)

The output of this command is:

(snip a bunch of unrelated stuff)
#119441: JavaScript aggregator/compressor by m3avrck and others.

Since the #number corresponds to a node ID on, I now know that this bug originated from the JS aggregation patch, and I also know that I should harras Ted next time I see him, and not Steven. ;)

CVS annotate - web version

It's also possible to use the power of this command without using CVS at all! provides a handy web-based CVS browser and you can use the same technique with it.

  1. Browse to includes/ to view a list of log messages for that file. (incidentally, you can use the "Sticky tag" drop-down at the bottom to view previous versions of the files [DRUPAL-5 = Drupal 5, DRUPAL-4-7 = Drupal 4.7...])
  2. Click the annotate link next to the first revision in the list.
  3. Hit Ctrl/Cmd+F to use your browser's search to find the line in question (1769). This will show you output like the following:

    CVS Annotate - Web style

    As you can see, this still has the same information as the command-line version, just is laid out a bit differently.

  4. Take note of the revision number (1.649). Incidentally, you can click that number to get a "diff" of the changes that were made during that commit.
  5. Go back to the top and click Revision log to go back to the initial screen showing all the commit messages.
  6. You should be automatically skipped down to the place where that change was introduced. And here you go, the same result as we discovered in the command-line version:

    CVS log - Web style

  7. Head over to the referenced issue and read up on why the change happened for hints on how to fix it.

So there you have it!

Two ways to get at some really useful information for whatever ails you!

Angie Byron

Powered by Drupal!




It's nano, not pico... and yes, I'm a total wuss. :-)



Darn you, line 1769! Why

Darn you, line 1769! Why must you mock me so?!

Too funny, now I won't be able to see an error message without cursing the line number for a week.



Why not ask

Looks a little bit like a workaround for asking to me. Why not just ask Steven what he had in mind when changing the code? But anyway, good demo of the annotate feature!


Mikkel Høgh

Lots of reasons, really.

There's lots of reasons for taking a different approach than just asking:

  • The original coder might not remember what he was doing 18 months ago.
  • You don't want to bother the original coder.
  • You are a Drupal core committer and really needs to know what's going on
  • The original coder is sleeping, on vacation, grumpy, or like in the actual case with Steven, is not doing Drupal any more…

Also, figuring out things for yourself can be fun – sometimes, at any rate :)