24

I've been a programmer now for over 11 years, and am just starting to get into version control for real. The places I've worked at have never really used version control (one committed at the end of each day, the others simply haven't bothered).

I am not happy with the way that I've been taught to version control (programme.js, programme.js.bak, programme.js.bak.20110901 etc) and so have been teaching myself to use git.

I currently use it along with github to keep my .vimrc file current across 4 machines, but I'm never sure when I should consider a change a commit, and when it's just a change which should be included along with another commit. I have started to use it for javascript development too and find it awesomely useful :)

My question is: At what point do changes become a commit? As I said, the only company I've worked for who used version control did it at the end of the day - this doesn't seem sensible to me. I feel that they should be more atomic. But my question is how atomic?

Is a bug fix for a function enough for a commit? Should I fix three (unrelated) functions and commit them all at once? Should I commit after changing the condition in an if statement?

On personal projects, I commit after any change. I personally find that useful, but I don't know if it's bad practice or annoying.

How do you do it, how does the industry do it, and what are best practices?

(I'm a web developer so work on short projects - perhaps a month long)

4
  • 9
    Commit locally all the time. If you fix a bug, and it takes 20-30 local commits, you can always rebase/tidy up the history before you push it to the server (i.e. one commit undoes an earlier commit). When you're commiting locally, you're more concerned with not losing your work (or deciding the change you made needs to be undone) than having a tidy history.
    – Rob
    Sep 25, 2011 at 21:39
  • 1
  • @Rob If you fix a bug and it takes 20–30 local commits, so what? Keep them; they'll make later bisection easily. I really don't get the fear of adding commits that I sometimes see. May 18, 2018 at 1:09
  • 1
    Commit when you would cry if you lost your work. Use branching to chunk up work and squash those commits together when merging, to make meaningful pieces of work. Nov 19, 2020 at 12:16

6 Answers 6

17

Each individual change should be one commit. A few things to consider:

  • Having stuff committed means that you can roll back. Assume you have a bigger task to be done. You're 50% done, that part looks good so far. Then you continue and break something massively by some mistake. Having the commit in between means you can go back there and didn't loose all of the work.
  • Version control is not a place to dump data and forget. Version control provides a history. Lateron you can use the history, including my favorite annotate feature, to figure out why a change was made (and who is responsible) this often helps. But to work properly the change should be small and self contained.
  • When working in teams it's great to have people reviewing it (actually even when working alone this would be great ;-) ), for a review it's good to have small parts which can be reviewed without being mixed in between unrelated changes.

Looking at git specifically, it allows local commits which are not visible to other people, so you can even commit broken code locally and fix it with a later commit before pushing. git commit is very fast so committing locally doesn't really interrupt the development process. Git also allows rewriting commits, so many commits can be rewritten into one before being pushed, which makes it easier to review - while rewrites are dangerous and should be done with care (don't rewrite after push etc.)

1
  • The bit about answering "why?" questions is probably the most important one. Good commit messages provide answers and insight in what is inside. Take great care in crafting good messages. Nov 19, 2020 at 12:18
23

When it comes to git, I believe one should commit as often as possible - some people commit every successful compilation. Don't confuse commits with pushes - a local commit does not have to be pushed (and with git, you should use many branches as they are cheap).

This should be the rule all around, but some SCMs are too slow for such a rule.

Personally, when using SVN, I try to commit several times a day and only when I am certain the code is in good condition (ie compiling and passing all its tests).

4
  • 2
    Brilliant - thanks :) The reason I chose git was because it could handle many commits/branches without a performance hit. Thanks for making me realise the difference between commit and push - normally I did both together, but doing many commits to one push seems much more sensible :) Sep 25, 2011 at 20:09
  • 2
    Multiple 'excessive' commits are easy to squash into one neat commit just before pushing, so there's no fear that frequent commits add noise to history (in master repo, at least).
    – 9000
    Sep 26, 2011 at 22:58
  • 1
    thats what Squash is for!
    – Venki
    Feb 24, 2012 at 0:13
  • @Venki But don't squash too often. As long as each commit is a known-good state, it is better to preserve them: that makes the history clearer and helps future maintainers. Jan 20, 2018 at 9:03
13

You commit when you can write a commit message (you write those right... :) that clearly describes the single new feature/function/bugfix/improvement included in the commit.

3
  • Totally - write commit messages with every one :) I was just wondering what makes a sensible commit - should it be a big job with 200 new lines of code, or a simple 2 line change/bug fix. I sometimes feel that I commit too often. Sep 25, 2011 at 20:11
  • 3
    A single bug fix is for sure a single commit in my world. 200 new lines sounds a little much for me, I would commit when I have something working (and unit tested) to know I have committed the latest working codebase all the time.
    – Kristian
    Sep 25, 2011 at 20:16
  • 1
    I'd suggest to commit even more often. Some commits get no message, except for "fixup XXX" since they only contains small fixes for other commits not yet pushed.
    – maaartinus
    Oct 15, 2011 at 13:42
3

If you are fixing independent bugs, they should be seperate commits. The reason being, if you later find a problem with you fix for bug A, and want to reverse it, it is much easier if it is not combined with bugs B and C. Especially if there have been additional code committed before you found the problem. The same logic applies to features as well. Basically, the smallest unit of working code that someone else can checkout and use. Even if that someone is you on another machine.

3

Small commits aren't exactly that bad when they are clearly about fixing specific things. It's understandable that revision history can get crowded but it can also provide interesting insights about development style of the project team. When new developer joins the project, it can be useful for him/her to read revision history list if the changes are described clearly enough.

Still, there are some guidelines that vary project by project. Some have set of tests that must be run successfully before code can be committed, others are configured to run tests automatically after committing (useful example of public Continuous Integration test service is Travis CI).

Answer will also vary by the type of version management system used in the project. Having mostly used DVCS type tools, I feel that it can be useful reminder for myself to make small commits as it also works as partial documentation. Too large amount of smaller commits can be confusing at first but according to research, most of the commits in Open Source projects are small. There might be variance in how internal development works but often it's the little things that start to annoy in tools and small changes often are enough to fix specific problems.

Some of possible reasons for keeping it small:

"You should try to split your changes into small logical steps, and commit each of them. They should be consistent, working independently of any later commits, pass the test suite, etc."

Have found useful alias for seeing list of git commits in console. lg has really helped to see changes faster and more clearly than various other commit list views:

# Show history in short format with colors
alias lg="git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset' --abbrev-commit --date=relative"
1

I always strive for having my commit log looking like the changelog for my program. That's not an achievable goal, but something to strive for. It pretty much defines that I want a separate commit for each new feature and each bugfix, but not too many.

Additionally when working in a team, I think of a commit as a letter to a fellow developer, describing the change I have made. I don't want to spam my fellow with every little commit I make when developing a new feature. It will leave a lot better impression if I just produce one larger commit, as if I had written the feature flawlessly on my first attempt.

But on the other hand I don't want to fall into lonely darkness... spending a month crafting one huge perfect commit. I want to keep my fellow developers aware of my progress. Any big feature can usually be split into meaningful pieces. So as a rule of thumb, one public commit per day should be the minimum.

2
  • 1
    ...flawlessly on my first attempt - not for me. I'd much rather have the benefit of knowing the things you tried that ended up not working. But then again, if you produce flawless code why use version control at all ;)
    – CurtainDog
    Feb 15, 2013 at 6:12
  • "I always strive for having my commit log looking like the changelog for my program. That's not an achievable goal, but something to strive for." If I understand correctly, then I strongly disagree. Your changelog is the high-level view of what changed, while your commit messages should be at a much lower level and reveal the details that aren't worth putting into the changelog. They should be related, not similar. • "It will leave a lot better impression if I just produce one larger commit" Not to me. It would give me the impression that you're a liar. I want the log to reflect reality. May 14, 2018 at 2:19

Not the answer you're looking for? Browse other questions tagged or ask your own question.