Next: , Previous: The pserver access method is STILL not working, Up: Some Real Life Problems (With Solutions)

My commits seem to happen in pieces instead of atomically

That's because CVS commits happen in pieces, not atomically. :-)

More specifically, CVS operations happen directory by directory. When you do a commit (or an update, or anything else, for that matter) spanning multiple directories, CVS locks each corresponding repository directory in turn while it performs the operation for that directory.

For small- to medium-sized projects, this is rarely a problem – CVS manages to do its thing in each directory so quickly that you never notice the nonatomicity. Unfortunately, in large projects, scenarios like the following can occur (imagine this taking place in a project with at least two deep, many-filed subdirectories, A and B):

  1. User qsmith starts a commit, involving files from both subdirectories. CVS commits the files in B first (perhaps because qsmith specified the directories on the command line in that order).
  2. User jrandom starts a cvs update. The update, for whatever reason, starts with working copy directory A (CVS makes no guarantees about the order in which it processes directories or files, if left to its own devices). Note that there is no locking contention, because qsmith is not active in A yet.
  3. Then, qsmith's commit finishes B, moves on to A, and finishes A.
  4. Finally, jrandom's update moves on to B and finishes it.

Clearly, when this is all over, jrandom's working copy reflects qsmith's changes to B but not A. Even though qsmith intended the changes to be committed as a single unit, it didn't happen that way. Now jrandom's working copy is in a state that qsmith never anticipated.

The solution, of course, is for jrandom to do another cvs update to fetch the uncaught changes from qsmith's commit. However, that assumes that jrandom has some way of finding out in the first place that he only got part of qsmith's changes.

There's no easy answer to this quandary. You simply have to hope that the inconsistent state of the working copy will somehow become apparent (maybe the software won't build, or jrandom and qsmith will have a conversation that's confusing until they realize what must have happened).

CVS's failure to provide atomic transaction guarantees is widely considered a bug. The only reason that locks are not made at the top level of the repository is that this would result in intolerably frequent lock contentions for large projects with many developers. Therefore, CVS has chosen the lesser of two evils, reducing the contention frequency but allowing the possibility of interleaved reads and writes. Someday, someone may modify CVS (say, speeding up repository operations) so that it doesn't have to choose between two evils; until then, we're stuck with nonatomic actions.

For more information, see the node Concurrency in the Cederqvist manual.

Karl Fogel wrote this book. Buy a printed copy via his homepage at

copyright  ©  November 19 2019 sean dreilinger url: