I've been thinking about this issue as well for a project I've been tinkering with, a RESTful database implemented in Python .
One idea I had was to add a special transaction resource (at /transactions, or some other agreed-upon location). When you POST to the transaction resource, it sprouts a new child with a unique ID (/transactions/12345). That URL now duplicates the entire structure of the database. So if the database had a resource called /Users/Bob, there is now a /transactions/12345/Users/Bob resource. The client can do all of his database operations within his transaction sandbox, then POST to /transactions/12345 to commit.
I think this is a fairly RESTful way to implement transactions. The best part IMO is that it allows you to add transactions without adding any HTTP headers, additional verbs, etc. The only downside I see is that there are now multiple URLs for a single resource. You might be able to solve that by using HTTP 301 to point clients at the canonical one if they try to touch something that's already been committed.
Heh. Gary, we've independently invented the same thing :-) Check out the link I posted above.
Yes, I posted my reply here before reading through that thread. :) It seems like the only real difference between our approaches is that when you create a transaction, you tell it which resources you'll want to touch. I prefer to "branch" the whole URL space, rather than some subset. That way, your code doesn't have to think about which resources it'll touch until it does the touching. :)
I haven't got the book yet, but "the transaction is a resource" is a pattern spelled out in this review by Jon Udell: http://blog.jonudell.net/2007/05/24/restful-web-services/ so apparently it's in the book.