Source code management is an essential tool that most developers learn about at their first job. Source code management is used across every programming language without favor or discrimination, but you don’t always see it in smaller shops, used even in small projects, or even used with database development. It should be an essential component of how developers work; the most basic and default process of development teams. Why do we often get it wrong?
Let’s summarize this issue down to just 10 rules which will help you and your team do a better job of managing source code.
1. Stop using VSS
I case you haven’t heard, Visual SourceSafe (VSS) from Microsoft is dead. It’s been scheduled for end-of-life support for years, with the latest version (Visual SourceSafe 2005) ending extended support in 2017. VSS was a good product when it was first released, but by 1998 it wasn’t a market leader for features, stability, or ease of use.
It also is difficult to use with anything outside of Microsoft tools, and is now seen as almost impossible to keep working reliably or without the significant risk of data loss. The latest product from Microsoft is now Team Foundation Server (TFS), and that is the future according to Microsoft.
2. Source Control is Required
If it isn’t in your reliable source code repository, the development isn’t complete. If you think that having a million lines of source code on a development laptop is an indication of successful development, you are really one hard drive failure away from having nothing. How does a team combine there different projects and merge them into one solution? What if you need to roll back a feature to an earlier version, and the developer didn’t save a backup copy of the source file before they made changes?
Once you take the mindset of committing to a source code repository, these problems disappear and your development of best practices start solve problems and make development easier and faster. You can break tasks into smaller units so you can commit atomically. You integrate changes from more developers into one project more frequently. You insure yourself against those local hardware failures and user mistakes.
But more importantly you can show that you and the development team are actually producing something. Declining burn-down charts or ticked-off tasks lists are great, but what do they actually reconcile with on the project plan? Unless they correlate with working code in source control, they mean nothing to management.
3. Commit early and often
Every developer should be on a formal and informal checkin schedule. The developer should be encouraged to commit any changes as often as possible, with at least one required checkin each work week. The reasons for this are simple:
- Every committed revision gives you a rollback option. If the developer makes a mistake, will they be rolling back one hour of changes or one week?
- The risk of a merge nightmare increases dramatically with time. Merging is never fun, but if you’ve not committed code for days and you suddenly realise you’ve got 50 conflicts with other people’s changes, you’re not going to be happy.
- It forces you to isolate features into discrete units of work. Let’s say you’ve got five developers working on one new major feature of the project that is expected to take two weeks. You’ll have people working on their part of the project and not committing until the end of that period because they’re trying to build the whole solution as one logical unit. The changes are actually much smaller units that should be committed as smaller units into the repository.
When you work this way, your commit history inevitably starts to resemble a semi-regular pattern of multiple commits each work day. Of course it’s not always going to be a consistent pattern, there are times we stop and refactor or go through testing phases or any other manner of perfectly legitimate activities which interrupt the normal development cycle.
However, when you see an individual – and particularly an entire project – where you know there should be in a normal development cycle and there are entire days or even multiple days where nothing is happening, you should get very worried.
4. Always Inspect Changes
Committing code into source control is easy; sometimes too easy! What happens is people inadvertently end up with a whole bunch of junk files in the repository. The repository gets polluted with things like debug folders and other junk that shouldn’t be in there. People also might commit files without checking what they’ve actually changed. This is real easy to do once you get things like configuration or project definition files where there are a lot going on at once. It makes it really easy to inadvertently put things into the repository that simply weren’t intended to be committed and then of course they’re quite possibly taken down by other developers.
The solution is simple: you must inspect each change immediately before committing. The whole “inadvertently committed file” issue can be largely mitigated by using the “ignore” feature many systems, including TFS, implement. As for changes within files, you’ve usually got a diff function to compare files.
5. Write Meaningful ‘commit’ Messages
The whole idea of ‘commit’ messages is to explain why you committed the code. When you commit the changes, write a meaningful message you the next person reading the reason will understand the reason. Whatever it is, there’s a reason for it and you need to leave this behind you. You might not remember why you did what you did 2 years from now, or your co-worker might not understand why you did what you did tomorrow without a decent message.
Your ‘commit’ messages are absolutely invaluable when it comes to tracking down errors.
One last thing about commit messages; subsequent commit messages from the same author should never be identical. The reason is simple: you’re only committing to source control because something has changed since the previous version. Your code is now in a different state to that previous version and if your commit message is accurate and complete, it logically cannot be identical.
6. Commit Your Own Changes
As unusual as this sounds, in some environments only the lead developer is allowed to commit the group code, usually after they have reviewed the code, cleaned up the teams messy comments or unneeded files. It’s pretty easy to observe this pattern from a distance. Very infrequent commits (perhaps weekly), only a single author out of a team with multiple developers and inevitably, conflict chaos if anyone else has gone near the project during that lengthy no-commit period.
There are two major things wrong here: Firstly, source control in not meant to be this virginal, unmolested stash of pristine code; at least not throughout development cycles. It’s meant to be a place where the team integrates frequently, rolls back when things go wrong and generally comes together around a single common base. It doesn’t have to be perfect throughout this process, it only has to achieve that state at release points in the application lifecycle.
The other problem is that from the developer’s perspective, this model means you have no true source control. It means no integration with code from peers, no rollback, no logging, nothing! They are just writing code and waiting to hand it off to the team lead at some arbitrary point in the future. This is not a good thing.
7. Database Versioning
How will you track changes to the database without versioning?
Most source code repositories work by simply versioning files on the file system, like HTML pages, images, CSS files, project configuration files, and anything else that sits on the file system in nice discrete units. What changes the proposition of database versioning these days is the accessibility of tools like TFS that allow you to create a database project to store your database schema as a TFS project.
Honestly, if you’re not versioning your databases by you’re carrying a lot of risk in your development. You have no single source of truth, no rollback position, and no collaboration with the team when you make changes.
8. No Compilation Output
Anything generated by the compiler shouldn’t be included in the source code repository. This prevents issues when a developer checks out the source not overwrite their compiled objects unique to their laptop development environment. This prevents merge issues, but it also saves space in the repository for what you really want to store: Source Code.
Once paths such as “bin” and “obj” are set to ignore, everything gets really simple. Do it once, commit the rule and everybody is happy.
If you want to save versions of executables or project binaries, create a network share and save the objects on the network.
9. No Personal Settings
Developers should not commit personal configuration or preferences as part of their commit collection. This would include .suo or .user files, and they just add to confusion and extra work if it is allowed. This is just as easy as ignoring those files again.
10. Include Dependencies
This might be the last of the Ten Rules but it’s a really important one. When an app has external dependencies which are required for it to successfully build and run, get them into source control! The problem people tend to have is that they get everything behaving well in their own environment with their own settings and their own local dependencies then they commit everything into source control, walk away and think things are cool. And they are, at least until someone else who doesn’t have some same local decencies available pulls it down and everything fails catastrophically.
Just to be clear, if there is already a process in place to make sure all developers are working in a development environment that verifies everyone is working with the same frameworks, and the dependency issue is handled well enough that all developers are in sync, then you don’t need to also include this as part of the source code repository.
It’s not always possible to include all dependencies, but it’s usually a pretty easy proposition. This makes it easy for anyone to check out the source and run it from their environment from day one.
None of these rules are difficult to implement. These rules are fairly basic: commit early and often, know what you’re committing, verify it should actually be in the repository, explain your commits with great comments, do your own commits, include the database, and don’t forget the dependencies. You can read more about TFS here. For a comparison of the different options available, you can read this article.