Sunday, August 18, 2013

FFS! Learn how to use source control properly

This article was prompted by a tweet by Nat Pryce:
I thought - similarly - how about source control?

I have seen flaws with how source control is used at almost every company I have worked at. This article is about the ones that make me think "FFS! Learn how to use source control properly". The terminology I have used is from subversion - but the ideas are applicable to all source control systems.

What everyone agrees on (right?)

All files needed to run the build should be in source control, or generated from files (e.g. build files) that are in source control. That is, having done a clean check out from source control, on a new development machine, I should be able to run the build and it should work. Everything needed for the build to work, e.g. libraries or things that need to be installed, should either be in source control or copied/installed on the machine as a result of running the build. (That is the ideal - sometimes it is tolerable to expect some things to already be installed - but that is not ideal).

Don't make me think about which files should or shouldn't be committed

All files generated by your build should be ignored by source control. That is, having run a build, if I haven't added any files myself, I shouldn't see any files available for adding to source control. That is so I don't accidentally commit files that shouldn't be committed.

Running the build should not modify any files that are in source control. That is, having run a build, if I haven't modified any files myself, I shouldn't see any file modifications available for committing to source control. That is so I can see only the changes I've actually made and commit all of them.

Every-day use of source control

Before committing, a developer should update and run the build to check that it is safe to commit. (There are some valid exceptions - I won't go into that now). Some source control systems allow a commit to the central repository even when the working copy is not up-to-date ("svn commit" allows this in some cases, "git push" doesn't allow this at all). If you commit without updating, then the first time the code has been integrated is in source control and so you can't be sure it's going to work).

Commit everything - all modifications, additions and deletions. If you don't commit everything then you might have committed a non self-consistent set of files which don't work. If you have multiple logical changes that need to be committed, you might want to commit different sets of files in different commits in order to describe each change. That can be OK, but it is better to only have one logical change in your workspace at a time and commit that in its entirety. You will probably benefit from working in smaller steps, committing each logical change separately from the other. (When I say "one logical change" that might be as small as a one character change to fix a typo.) If you commit logically separate changes one at a time in their entirety you will end up committing many times a day, and that is a good thing. Having a mechanism to shelve/unshelve changes can be useful for allowing you to make logically separate changes one at a time, safely.

Finally

There are many different ways to use source control that are perfectly acceptable. Please comment if you disagree with the things I have written in this article.

Copyright © 2013 Ivan Moore

5 comments:

Nat Pryce said...

Oh great! Now I have to write "FFS! Learn to use Make properly".

Chris Tucker said...

I'm curious as to your stance on "Before committing, a developer should update and run the build to check that it is safe to commit." when the system is an integrated build environment with check in dependent on a build machines results, a-la TFS?

Ivan Moore said...

Hi Chris,

I also said "There are some valid exceptions - I won't go into that now". The use of "Pre-Tested Commit" (as JetBrains calls the equivalent feature in TeamCity; other CI servers are available) is beyond the scope of this article. And that's all I want to say about that, for the moment.

Nicola Musatti said...

Being able to commit locally without committing globally is a good reason to prefer a distributed version control tool such as Mercurial or git. It makes merging before committing safer and it may also solve the many small commits vs. one big commit dilemma automatically, by allowing you to perform many small commits locally and push them together to the central repository.

Unknown said...

It's so depressing that you had to write this. :-/