|< Day Day Up >|| |
Deciding on and installing a source code control system is only half the battle. You also need to learn how to use it effectively. While I can’t offer detailed instructions on every product out there, I can pass on quite a few tips about using source code control effectively. Some of these might not be applicable to your particular project or platform, but in general, I think you’ll find this a useful list of best practices.
What belongs in your source code control system? Not just source code! You should use the repository as a central place to store and manage any artifact that is not built from other artifacts.
“Artifact” is used here as a general term for anything having to do with your software product. Here are a few things you might consider storing in your source code control system:
Windows Installer databases
Database build scripts
Icons, bitmaps, and other graphics
Informal development notes
The goal is simple: if someone comes to you a year from now and wants you to rebuild version 1.0.5 of your product, you should be able to pull everything that you need out of the source code control system.
Note that this doesn’t mean that you need to store everything in the system. Consider documentation, for example. If you’re using a product such as RoboHelp to build help files and other documentation, there’s no need to store the final help files and documentation in the source code control system. Instead, store the RoboHelp files, and you can always re-create the documentation if you need to by running the source files through RoboHelp again.
I make one exception to the rule of not storing generated artifacts: I store log files from my build and test tools. It’s useful to be able to look back and see whether a particular build was successful, and if not, what went wrong, without getting all of the source files and running the entire build again.
The goal is simple: If you pull the files for a particular release out of your source code control system, you should have everything you need to re-create the build exactly as it was that day. If your build process includes manual steps, your source code control system should contain documentation on those steps, and you need to keep that documentation up-to-date as things change.
As a corollary, once you store something in the system, you must manage it through the system—and this rule needs to be enforced across your entire organization. Don’t let developers (or anyone else) copy things off to a private sandbox with the intent of checking them in later. Once a file escapes from source code control, you lose the ability to easily re-create the state of your project at a point in time.
The cardinal rule of effective use of source code control is to work with as few files as possible at one time. If you’re working in a check-in/edit/check-out system, this means checking out only enough files to complete one task, and then checking them back in. If you’re working in an edit/merge/commit system, this means remembering to commit your changes at the end of each task.
This is important for several reasons. First, if you are working with a system that locks files, you can avoid locking other people out for longer than necessary. Second, by keeping your commits small, you vastly lower the chance of needing to merge two incompatible versions of code. Finally, by working in small chunks, you can keep the comments in the source code control system targeted and informative.
Whenever you check in a new file or make a change, be sure to put a comment into the system along with the code. Occasionally, developers think that the comments in the code should be sufficient; if anyone wants to know what happened, they can compare two versions and see what’s changed. This turns out to be a very inconvenient attitude when you want to view the entire history of a file and see how it evolved. (Developers with this attitude often don’t want to write comments at all; I’ll talk about that in Chapter 4, “Coding Defensively.”)
Labels (called tags in some systems) offer a way to mark a file version or, more usefully, a versioned set of files with some friendly name. This is useful because human beings are much better at remembering “Beta 1” than “Version 254” or “3 April 2004 10:12 AM” when they’re trying to find a set of files. But when should you apply a label to your files?
The answer is that you should label significant points in time. Certainly a public release counts as such a point in time, but there may be other events worthy of a label as well. Consider again the task of making a major change to your code. You might want to label the start of this change (assuming that you don’t do it in a branch) to make it easy to back up to before the change if you need to do so.
Depending on your system, you may find that it’s easier to retrieve files by label than by date. If that’s the case with your system, you might find it worthwhile to label every daily build.
When should you create a branch in a project under source code control? The answer is simple: You should create a branch whenever different developers in the same project are following different rules. In the example I used earlier (starting work on version 2.0 while finishing up version 1.0), one group of developers is checking in small, careful changes, while the other is roughing out the broad outlines of new features. That’s a good example of the need for a branch.
Branching is useful for exploration as well. If your main line of code is using a known, stable technique but you want to explore a faster and potentially unstable way of accomplishing the same objectives, you should create a branch to explore the consequences. If the branch works out well, merge its changes back to the main line. If not, just stop working in the branch.
Don’t create a branch just because you know you’re going to need it at some point in the future. If nobody is working on version 2.0 yet, then it’s too soon to create separate 1.0 and 2.0 branches. To do so only results in extra merging work as you try to keep the two branches in sync before they’re really needed.
Make sure that you handle branching by actually creating branches. Sometimes a developer will copy a project and check the copy into the source code control system as the basis for a new version. Don’t let this happen. If you do, then the files in the new version will not have any connection to the files in the original, making it impossible to trace their history back to their starting points.
If you know you’re going to merge code from a branch back to the main line of development, do the merge sooner rather than later. The longer you wait to perform a merge, the more likely you are to have to resolve incompatible changes in the other line of code. And the longer you wait, the more likely you are to forget exactly which changes you wanted to merge, and why.
Some bug-tracking systems offer an interface to some source code control systems. If your two products of choice work together this way, use the integration! When you check in a file in response to a bug report, be sure to note the bug number that it fixes. This will allow you to view the applicable changes directly from the bug-tracking system. For more on bug tracking, see Chapter 9, “Tracking and Squashing Bugs.”
If you’re working in an organization with several developers, you’ll likely end up creating your own “best practices” document, describing how your team handles builds and source code control. Consider checking that document into the source code control system too. In fact, you might create a special project in your system to hold nothing but documentation of company standards. That way, developers can always refer to the most recent version of the standards documentation, no matter where they’re working (at least, as long as they can connect to the source code control system).
|< Day Day Up >|| |