After years of dabbling with different version control systems and techniques, I wanted to share some of what I like and dislike in a few blog posts. To start this out, I want to talk about how I use VCS in a team environment. These come in a series of tips or best practices that I try to follow.
Note: This list is subject to change in the future.
Note: I edited this to make it more friendly, I was too opinionated when I first wrote this.
- Always use some form of version control for all aspects of software development.
- Development is an evolution. Looking back at where we were is an invaluable asset in that process. This includes data schemas and documentation.
- Reverting / reapplying changes is absolutely critical for efficient development.
- The tools I use:
- Code: Hg (preferred), SVN
- Database: TSqlMigrations
- Documents: Sometimes in code repository, also SharePoint with versioning
- Always tag a commit (changeset) with comments
- This is a quick way to describe to someone else (or your future self) what the changeset entails.
- Be brief but courteous.
- One or two sentences about the task, not the actual changes.
- Use precommit hooks or setup the central repository to reject changes without comments.
- Link changesets to documentation
- If your project management system integrates with version control, or has a way to externally reference stories, tasks etc then leave a reference in the commit. This helps locate more information about the commit and/or related changesets.
- It’s best to have a precommit hook or system that requires this information, otherwise it’s easy to forget.
- Ability to work offline is required, including commits and history
- Yes this requires a DVCS locally but doesn’t require the central repository to be a DVCS. I prefer to use either Git or Hg but if it isn’t possible to migrate the central repository, it’s still possible for a developer to push / pull changes to that repository from a local Hg or Git repository.
- Never lock resources (files) in a central repository!
- We have great merge tools now, merging sucked a long time ago, it doesn’t anymore!
Always review everything in your commit.
- Avoid committing without reviewing the changes in each file.
- If you leave to make changes during a review, start the review over when you come back. Never assume you didn’t touch a file, double check.
- This is another reason why you want to avoid large, infrequent commits.
- Requirements for tools
- Quickly show pending changes for the entire repository.
- Default action for a resource with pending changes is a diff.
- Pluggable diff & merge tool
- Produce a unified diff or a diff of all changes. This is helpful to bulk review changes instead of opening each file.
- The central repository is not your own personal dump yard.
- If you turn on Visual Studio’s commit on closing studio option, I will be very sad :(.
- Commit (integrate) to the central repository / branch frequently
- I try to do this before leaving each day, especially without a DVCS. One never knows when they might need to work from remote the following day.
- Never commit commented out code
- If it isn’t needed anymore, delete it!
- If you aren’t sure if it might be useful in the future, delete it!
This is why we have history.
- If you don’t know why it’s commented out, figure it out and then either uncomment it or delete it.
- Don’t commit build artifacts, user preferences and temporary files.
- Build artifacts do not belong in VCS, everything in them is present in the code. (ie: bin*, obj*, .dll, .exe)
- User preferences are your settings, don't override other team member preference files! (ie: .suo and .user files)
- Most tools allow you to ignore certain files and Hg/Git allow you to version this as an ignore file. Set this up as a first step when creating a new repository!
- Be polite when merging unresolved conflicts.
- Count to 10, grab a stress ball and realize it’s not a big deal. Actually, it’s an opportunity to let you know that someone else is working in the same area and you might want to communicate with them.
- Following the other rules, especially committing frequently, will reduce the likelihood of this.
- Don’t blindly merge and commit your changes. Make sure you understand why the conflict occurred and which parts of the code you want to keep.
- Apply scrutiny when you commit a manual merge: review the diff!
- Make sure you test the changes (build and run automated tests)
- Become intimate with your version control system and the tools you use with it.
- Avoid trial and error as much as is possible, sit down and test the tool out, read some tutorials etc. Create test repositories and walk through common scenarios.
- Find the most efficient way to do your work. These tools will be used repetitively, so inefficiencies will add up. Sometimes this involves a mix of tools, both GUI and CLI.
- I like a combination of both Tortoise Hg and hg cli to get the job efficiently.
- Always tag releases
- Create a way to find a given release, whether this be in comments or an explicit tag / branch. This should be readily discoverable.
- Create release branches to patch bugs and then merge the changes back to other development branch(es).
- If using feature branches, strive for periodic integrations.
- Feature branches often cause forked code that becomes irreconcilable. Strive to re-integrate somewhat frequently with the branch this code will ultimately be merged into. This will avoid merge conflicts in the future.
- Feature branches are best when they are mutually exclusive of active development in other branches.
Use and abuse local commits , at least one per task in a story.
- This builds a trail of changes in your local repository that can be pushed to a central repository when the story is complete.
- Never commit a broken build or failing tests to the central repository.
- It’s ok for a local commit to break the build and/or tests. In fact, I encourage this if it helps group the changes more logically. This is one of the main reasons I got excited about DVCS, when I wanted more than one changeset for a set of pending changes but some files could be grouped into both changesets (like solution file / project file changes).
- Avoid committing sensitive information
- Especially usernames / passwords
There is one area I haven’t found a solution I like yet: versioning 3rd party libraries and/or code. I really dislike keeping any assemblies in the repository, but seems to be a common practice for external libraries. Please feel free to share your ideas about this below.