Source control best practices

The following advices apply to the Mercurial source control system and assume the usage of the TortoiseHg client. See the Mercurial Kick Start for a more holistic tutorial. Also there's a nice tutorial regarding TortoiseHg and Codeplex.

Committing

  • Try to only include changes corresponding to a single task in a commit.
  • Push your commits often if you're working in a team.
  • Use descriptive commit messages. If a commit corresponds to an issue tracker ticket start the message with the ticket number.
  • Don't store assets (i.e. files generated from the source) in source control if possible, e.g. the bin and obj folder should be excluded.
  • When you rename a file tell Mercurial that you’ve renamed the file (you can use, there’s not a removed and an added one. This makes possible to maintain file history. You can also let TortoiseHg automatically detect renames.
  • If you use an issue tracker then have issues open for every non-trivial task. Then, having issues created, prefix commit messages with the issue ID, e.g. "#11: Fixing title" or somehow reference issues. If you don't use an issue tracker or commit something not related to an issue but your code base is large and consists of multiple distinct sections then prefix your messages with the section name, e.g. "Media Management: Fixed image upload". You can even use the two technique at the same time.
  • Discrete changes should go into discrete changesets. Try to avoid having multiple logical changes in the same commit as this will make it difficult to back out of certain changes if necessary.
  • Commit often if you have finished something. If you have something working, or a section done, commit it. It will make much easier to track changes instead of having one big changeset. If you don't want to clutter everybody else's code base with half-ready changes then commit them to a feature branch. If your code is not affecting anybody else's work (e.g. it's not something that every other developer also uses or that will be included in the next release, or in case of Orchard it's a module that's not yet enabled anywhere, or you work in your own feature branch) then the only criterion a commit must meet is that it should compile properly. This is to encourage frequent commits. If your code change affects somebody else's work too then of course you should take more care and test it.
  • If your repository uses subrepos: when you did some change to a subrepo then always commit the subrepo change into the main repo too in the end. The point is that everybody pulling the main repo will also get the current version of all subrepos too. This doesn't mean that you have to make a main repo commit for each subrepo commits (commits in the subrepo can very well be more frequent), but once you're done with a batch of work, commit that to the main repo too. Because of the same reason never push to the subrepo alone but rather push the main repo (what, the subrepo changes being committed to it, will also push the subrepo).

Branching

  • If you use branches for developing features prefix the branch names with something and use a pattern like "feature/[branch name]" to make those branches distinguishable from other branches.
  • Try to avoid merging branches with themselves. If you committed to a branch locally but meanwhile somebody else did the same first, after pulling do the following: instead of merging the two changesets rebase your changeset on top of the remote head. (See the Rebase documentation and the TortoiseHg Workbench documentation.) Be careful when using subrepos! If you already committed a subrepo to its top repo then you can't rebase the subrepo as it would cause incosistency in the top repo. In such cases simply do a merge in the subrepo if there is a more recent head changeset.
  • When doing work in a temporal branch and you want to merge the changes back to another branch and close the branch do it in the following order: close then merge and NOT merge then close as this will result in an unnecessary dangling head. See this SO post for more details. Always close a branch if you don't want to use it any more.
  • When doing work in a branch separated from the main line of development merge frequently from the main branch. Frequent, small merges are easier and less error-prone than big merges and also you'll be able to integrate your changes with the work done by others.
  • See the excellent "A Guide to Branching in Mercurial".

This page is part of the Orchard Dojo Library!

This page and many others here are part of the open source, portable package of Orchard goodies: the Orchard Dojo Library. The Library is freely accessible by anyone; just go to its repository to download its full content (you can even download the textual content of the Library as a big concatenated document in HTML), file issues or fork it! You can even edit it online on Bitbucket, just click on the Edit link in the upper right corner!