Wednesday, April 05, 2006

Today's Breakfast:: Sugar, Caffeine, and Subversion

A Trader Joe's chocolate bar with hazelnuts. A wasa cracker. A two-shot Americano in a large cup with one shot hazelnut flavoring (I wanted it a bit watery today). A piece of frosted lemon-poppyseed bread. A passably good low-fat roast chicken sandwich with stone ground mustard. A "Naked" brand pomegranate/blueberry juice. 1 gram of niacin. 900 mg. St. John's Wort. A handful of licorice allsorts candies.

As this strange breakfast shows, I'm a bit out of whack, pounding sweets and playing chicken with blood-sugar crash as well as courting an eyestrain headache. Yesterday was a 17-hour work day, from 8:45 a.m. to 1:45 a.m. the following morning, followed by a trip to the gym at around 2 a.m. (Yes, I left work shortly after the time and date hit the mysterious "01:02:03 04/05/06" mark). Yesterday's food intake was also a bit irregular. Breakfast was a capuccino, scone, and fruit smoothie. Lunch was mostly some cashews and walnuts eaten at my desk. Dinner was pizza provided by my boss, and some soda, which I rarely drink. Late night snack (after getting back from the gym) was a yogurt, crackers, and some cheese.

There was way too much refined sugar, a distinct lack of vegetables, (un-juiced) fruits, and (un-refined) grains. I should have skipped the candy bar, the lemon poppyseed bread, and the candies, and added a piece of whole-grain toast with peanut butter and maybe a banana. The large number of calories is not too abnormal after a very long night. I'll be trying to improve on that in the days ahead, but I guess it could be worse.

What am I working on? We are preparing to deliver a software build, and trying to integrate a number of new features. This involves some heavy lifting using Subversion, merging several branches, including merging several distinct changes sets from one branc and several more from a branch-from-a-branch, and merging this with with another branch from the trunk, while the trunk itself has undergone some major restructuring while we were away. This means a considerable number of files with conflicts, and getting some of our developers to do the required three-way merge with tools they haven't used before.

Typically, when you want to merge a branch back into the head, you might start by merging the changes made onto the trunk into the branch. This will get you a working copy of your branch that includes the changes that happened on the trunk while you were away. You can test this, and commit it, without messing with the trunk, and when you are satisified you can merge with the trunk, which should produce a working copy of the trunk that adds only the changes you made in the sandbox, then test again and commit. This is perhaps the most conservative strategy, but other strategies are possible, such as merging your changes directly into the trunk, or merging into a different branch.

You don't merge _files_ -- a merge means generating a change set, or set of diffs, and then applying it to a working copy. So you specify a series of revisions. Let's say again that you want to merge changes from the trunk into your branch. Typically, you would specify a range of revisions that included changes made on the trunk from just after the revision that created the branch up to the present, or head. This gives you a set of diffs.

Subversion then attempts to apply these diffs to your working copy of the branch. At this point I do a little hand-waving and say "and then a miracle occurs." I think that it may make a second set of diffs, or at least one diff between the starting file and the head of your branch, and then try applying both sets of diffs to the file to see what happens. If it can figure out unambiguously what changes to make, it just goes ahead and makes them, and you have an uncommitted file with both sets of changes (although whether the two change sets still create a completely sensible piece of code, Subversion can't tell you). If Subversion finds a place where it can't apply both changes to the file because they overlap, or at least because the context-sensitive patch process thinks they overlap, that file will get confict markers showing the parts that Subversion could not figure out how to merge.

Conceptually, you then have the original version of the file, a temporary version made by applying patches to the trunk, a temporary version made with the patches applied to the branch, and you're trying to produce a fourth file that combines these three -- a three-way marge. TortoiseSVN provides a nice graphical tool to help you pick which changes to apply and tell it when the conflicts are resolved. It does its best to make sure you really have gotten rid of the conflict. It won't let you commit the file until you've told it that the conficts are resolved, and it warns you when it thinks you haven't really removed the conflict markers.

Most of the time the conflicts make sense, but because the tool uses a somewhat conservative context-sensitive diff, it can get out of sync. If the identical patch has been applied in both places, it does not seem to recognize that this is not really a conflict and just pick one. Changes in line endings, problems with editors that insert NULL characters, or changes involving tab characters or spaces can also cause grief, so it is important everyone has the same idea of what the basic file format should look like.

For a decent-sized project, you might have hundreds of files that are merged automatically without conflicts, and perhaps dozens of conflicts. The fact that it is even possible to do this in a coherent, controlled, and fairly well-understood way (in fact, I was able to give a more-or-less clear explanation of what we were doing to Grace, who has never programmed a computer, and she seemed to understand it), means I want to give some major props to Subversion. Armed only with a few doodles showing the trunk and branches and direction of merge, it is mostly finished. The developers have done a fantastic job. The TortoiseSVN tool is also very nice. We've had only a few glitches (for example, identical binary files from the branch and the trunk flagged as conflicted, some directories getting stuck locked and svn's cleanup feature won't fix it), but nothing major.

I'd still like to experiment someday with darcs and some of the "fully distributed" paradigm revision control tools, but as far as I'm concerned, for production work, svn rocks! I could do this kind of thing with CVS, but I'm glad I don't have to. Subversion has handled all our rearranging of directories and adding and removing files flawlessly. Rearranging the project structure is downright painful in CVS. And trying it with tools like RCS or SourceSafe that don't support the general CVS paradigm would be incredibly painful.

So, to bed around 3 a.m. Some difficulty getting to sleep. About five hours of somewhat broken sleep. Woken up for good by 9:30 a.m. by the contractor who showed up to start tearing out the ceiling of Isaac's bedroom. There's a leak in the roof we've been complaining about for a year, and subsequent water damage has been working its magic in the ceiling. Isaac has been sleeping on the couch for some time now because of mold in the ceiling and carpeting (although we usually catch the water). Building management in its wisdom seems to be repairing the ceiling _before_ successfully repairing the roof.

The good side is I've been at the gym Sunday, Monday, and Tuesday (if you count 2:00 a.m. Wednesday morning as Tuesday). I am trying to establish the habit of going to the gym for at least a half-hour on a treadmill every weekday.

Back at work by about 10:30, with calls and voice-mail messages waiting for me as I come in. Ah, the joys of a build crunch!

No comments: