60

When working on a project, the code may be developed reasonably fast in a single day or bit by bit for a prolonged period of few weeks/months/years. As code commits are becoming to be considered as a measure of project development, it doesn't really mean it has more code written than a project that has lesser commits.

So the question is when to really make a commit to the repository so that the commit is justifiable?

As a add-on: Is it a correct practice to measure a project's development based on its commits?

  • 9
    Most things that are easily quantifiable are bad metrics because they are oversimplified or can easily be gamed to perform well against the specific measurement. – unholysampler Jun 14 '11 at 15:26
  • Thank you all for the inputs. There are many valid reasons to make a commit which is distributed over the answers, and I cannot accept multiple answers, I am accepting the answer with highest votes till now. But I take-in all your answers. – user22662 Jun 14 '11 at 16:05

11 Answers 11

79

You commit when you have reached a codebase state you want to remember. There are a lot of reasons why you might want to remember a particular codebase state, so there can't be hard-and-fast rules on when to commit. However, number of commits is definitely not a measure of quality or progress.

  • 10
    I agree, with the addendum that the trunk is a different story. In order to check into the trunk on my team for example, it has to a) build correctly, and b) complete something. Any team member is free to create a branch though and it can be in whatever state they want it in. – Edward Strange Jun 14 '11 at 16:22
36

I like to think of coding as rock climbing in this context. You climb a bit, and then you put an anchor in the rock. Should you ever fall, the last anchor you planted is the point that secures you, so you'll never fall more than a few meters. Same with source control; you code a bit, and when you reach a somewhat stable position, you commit a revision. Should you ever fail horribly, you can always go back to that last revision, and you know it's stable.

That said, if you work on a team, it's customary to make sure whatever you commit is complete, makes sense, builds cleanly, and doesn't break anyone else's stuff. If you need to make larger changes that might interfere with other peoples' work, make a branch so you can commit without disturbing anyone else.

It also depends on the SCM system you're using. Distributed systems typically make merging and forking painless and fast, and you can commit locally; this means you should commit a lot, and push / merge when you have done a substantial amount of work. With centralized systems such as svn or cvs, committing is more costly, and it affects everyone. Branching partially solves this issue, but because it happens on the server, it can be painfully slow, and merging can be cumbersome. So with centralized SCM's, there is often a more careful culture, where you only commit once you've done significant amounts of work.

As for the add-on: Please, please don't do that. Lines of code, number of commits, number of bugs found / resolved, etc., are all very bad measurements of quality or even quantity.

  • I presume the same applies for new branches, where all new development is commited to your own branch, which you will then push when the feature is ready? Ie. you might commit even a lot of incomplete code to your own private branch. – Juha Untinen Apr 27 '16 at 8:41
  • Yes, but to a lesser degree, because (see original answer) you won't disturb anyone directly. Depending on the SCM in question, it's usually considered good practice to clean up your commit history before merging upstream though (e.g. git rebase -i). – tdammers May 2 '16 at 9:29
13

If you're using DVCS like Mercurial or Git, you should commit to your local repository whenever you've done significant amount of work. However, only push it to shared repository only after it's working, self contained change that has been tested.

For non-distributed VCS (like eg. SVN) same logic applies, instead of local repository use private branch, instead of push — merge to main branch.

  • +1 Amazed this was not upvoted more. That was my first thought - dvcs or vcs – Michael Durrant Mar 12 '12 at 3:04
10

You should commit early and often.

I know of people who commit as often as every 90 seconds. Seriously. It seems to work for them. I have experimented with committing every time I save a file, which is probably more often than 90 seconds. Today, I probably commit about every 15 minutes. A VCS that allows you to squash multiple commits into one and that allows local commits (like git) makes this a lot easier.

How often should you commit? Hard to say, but probably more often than you are now. Keep committing more and more often, find a point that feels like it's absurdly too often, and then back off a bit. Chances are you'll end up with something reasonable.

You measure a product's development based on value delivered to its users. There is no other accurate measurement.

  • 1
    +1. When you combine BDD-As-If-You-Mean-It, Refactor Till You Drop, Atomic Coding, and a highly expressive language, 90 seconds can be a long time to go without a commit. – Jörg W Mittag Jun 14 '11 at 17:28
8

Commits are the building blocks of any version controlled data/code. Each commit should do exactly one of the following:

  • Add a new piece of data or function
  • Fix one or more bugs(one commit for each fix if possible) where fix can be:
    • Performance improvement
    • Correcting wrong code behaviour
    • Removing Typographical errors
  • Refactoring code or data without changing the semantics. This includes:
    • Rewriting code that behaves identical to original
    • Changing representation of data to a different format
    • Formatting code or data to meet project's formatting guidelines
  • Merge changes from another branch(either upstream/downstream)

Also when working in branches, commits must go to a branch that is more apt. Two commits should not have the same commit message(implying similar changes) but in different branches as it confuses the collaborators. A better way is commit to main branch and merge to the feature branch.

If committers follow the above rule, it becomes trivial to:

  • Revert a particular change with no side-effects
  • Identify behaviour altering code change from code formatting changes
  • Merge between different branches avoiding most conflicts
  • Collaborate with other developers who can pull your change with ease

Regarding measuring project's progress based on commits, it is possible if Refactoring commits and Bug fixing commits are not taken into account.

  • I think this answer must be the accepted answer, but probably the questioner was looking for a simpler explanation :) – Behnam Rasooli Apr 23 '16 at 16:09
7

Commit only when you have successfully unit tested the given function/module/functionality and you are reasonably assured that it is ready for integration or system testing.

And to answer your add-on questions - NO!! the measure of where the project is should never be determined by the number of commits...who knows what has actually been committed? Has it been successfully system tested or even unit tested. Just because it is committed - it doesn't mean it is production ready.

  • 5
    That would be true if you were committing to the trunk, but if you were committing to a feature branch or to a private branch, there's no need for it to be ready for integration. – Neil Butterworth Jun 14 '11 at 15:24
  • 1
    @Neil Butterworth: ...unless there are other developers working on the same branch with some dependencies on your code. – FrustratedWithFormsDesigner Jun 14 '11 at 15:25
  • @Frustrated In that case it should certainly be compilable, but I don't see that it should have to be ready for integration and system testing. – Neil Butterworth Jun 14 '11 at 15:28
  • 1
    Interesting dichotomy here between distributed and centralized vcs. With distributed vcs this would never be a concern since you can commit to feature branches locally and keep out of the way of any other devs. – George Mauer Jun 14 '11 at 18:47
  • 2
    @George - This is a false dichotomy. The real dichotomy is between the use of private (per developer) branches, or public (share by several developers). This is orthogonal to whether you're using a centralized of distributed VCS (however, DVCSs encourage private branches, as branches start as private until you publish them). – Stephen C. Steel Jun 14 '11 at 19:48
6

As a add-on: Is it a correct practice to measure a project's development based on its commits?

No. There was a daily WTF on why that is a horrid idea.

My general rule of thumb on committing code is to check in when I have completed a chunk of code and it compiles. Chunk is not really defined. If it's a small task, I might not check in until I'm done it. If it's larger, I might check in after each logical portion is completed.

But never check in if it doesn't compile. I know it seems like a stupid thing to actually say out loud, but I've had to explain it to people before.

  • 1
    +1 for compile warning. We had a piggy bank at the office where everyone had to put a fee into each time he/she committed something that made a build fail as a result. Sadly we got quite some money this way, at least initially :) – Ray Jun 14 '11 at 15:35
  • @Ray - at my last place, the fine went into the lotto fund. Alas, we never struck it rich off of this bad habit. :P – Tyanna Jun 14 '11 at 15:48
1

Make a commit when the code is ready to be shared with other users of the code - when it is relatively stable, safe, and properly tested.

And no, I don't think commits are a great metric for a project's development, because I know some developers that will commit every small and minor change, and others that will commit only huge major changes to functionality. How do you quantitatively measure the value of one commit over another?

  • Remember that with distributed systems, commit != share. You should push when you have something ready to be shared. – Rein Henrichs Jun 14 '11 at 15:54
  • @Rein Henrichs: Good point, though the source control here at work does not have that functionality (at least as far as I know). When something is committed, everyone else on the project can see and resync (and they usually do, sometimes blindly) to it. – FrustratedWithFormsDesigner Jun 14 '11 at 15:56
  • Which might be an indication that you could benefit from better tools. Anything that prevents frequent commits is an unnecessary hinderance. – Rein Henrichs Jun 14 '11 at 16:01
  • @Rein Henrichs: I won't argue that!! – FrustratedWithFormsDesigner Jun 14 '11 at 16:02
1

As soon as the corresponding task is done. A task is a part of a user story.

A task is done when:

  • the corresponding unit tests passe,
  • code is properly documented and
  • code is commited.

You can have a different definition of done.

I don't see the value in measuring the number of commits. However, if you see someone working for a long period on the same user story (or worse, stories), this is a smell.

1

Commit every significant change that you don't think breaks something. The only thing you should not commit are style changes because they do not embody change in logic. But otherwise, the smaller the changes you commit the better.

The smaller the commits, the more detailed you can document the thought process, which is one aspect of a good commit log. A good code review should not just be about the code result but also the thought process.

Also, having many small commits makes it easy to bisect, a way too little used feature of version control, one that saved me many hours of looking for needle bugs in haystack codebases.

Bisecting in short; Discover an issue in current codebase. Then, pick a commit in the changelog where you are sure the specific issue did not exist. Start with checking out the commit right in the middle between the "good" and the "bad" version. Test to see if the issue is still present. If it is, you need to look further back, at the middle of the "good" and the previously tested commit. If the issue is gone, it was introduced after this specific change, so you need to check out the middle between the "bad" and the previously tested commit. Repeat. Eventually you will end up with the commit that introduced the problem. But only if you have small commits, otherwise you will just know in which big pile of changes the issue came to exist.

Here is how it works with Git but the principal applies to any version control.

  • this doesn't seem to offer anything substantial over points made and explained in 10 prior answers. Besides, the last paragraph seems to refer to git-specific feature while the question appears to be not about git – gnat Aug 12 '16 at 10:10
  • Bisecting is not git specific. It can be done with any type of version control, this was just an example as I'm aware Git has it build in. – Jasper Kennis Aug 18 '16 at 12:55
-1

When:

  • it builds (ALWAYS)
  • unit tests pass
  • it works (unless it is clearly marked as "work in progress")
  • the benefits of saving the state of the code outweight the hassle of running the tests, thinking of a good commit message and resolving any merge conflicts during the commit process
  • upvoted for this is our best practice. – jersoft Aug 12 '16 at 9:11