views:

167

answers:

5

I know the question has been asked before how often to commit with a DVCS. All answers have one thing in common--as often as possible. But they're usually something like, after finishing a thought, a user story, getting code that compiles, or passing tests. I was thinking, given that a DVCS gives you you're own repository, with very cheap commits, doesn't it make sense, to commit after every change to a file? After all, this is what happens in NetBeans, and you get a nice free "time machine" without even asking for it. If not every change, then at least every save, or compile.

Does this make sense, or do I have the wrong idea about DVCS. My feeling is that this not the workflow most people have with DVCS.

+2  A: 

I would not commit after every save, unless you save infrequently. I sometimes save after every LOC that I change. It certainly wouldn't make sense to commit each of them, because then the commits would be incomplete patches and broken or un-buildable functionality.

My philosophy is to commit after every cohesive change to functionality or style. A major feature can be several commits, but each one should stand on its own - you should be able to move that patch to another repo and still be welcome there without breaking anything. If you have to commit in violation of this rule, for example to change branches (and you don't want to stash) then you should prefix your commit message with "wip" for work in progress.

A shorter way to put it: if the idea of committing after every save doesn't sound like a huge waste of time to you, then you aren't saving often enough.

Tesserex
What about in a "feature branch", which is not going to pushed upstream anyway (let's say rebased and then merged to your main branch)?
blockhead
In a feature branch that you don't plan to publish, you can do whatever you want (because you're not publishing it, so you're not creating inconsistencies if you go back and change it later.) Try some things out and figure out what works for you.
David Winslow
+1  A: 

One of the standard reflex programmers have is to press Ctrl+S (Or :w). If you end up having them in your team, your repo is going to have a huge number of commits. Heck, git hashes doesn't even directly tell you how many there are.

You shouldn't really do it, from the managerial perspective. You shouldn't really have to choose from hundreds of commits, if I have to revert to another version I had this morning.

That said, there is nothing that prevents you to do so from a technical standpoint. Git only adds more commit objects and pointers to the blobs, most of which already exist.

If you go ahead and do so, you should squash the commits from this branch into another branch on merge, so that you, or the other repo users, can make sense of the commit messages and individual commits.

Lakshman Prasad
+3  A: 

That would make sense only if you clean your history before:

  • pushing it to any other repo
  • or even merging/rebasing it to any other branch within your local repo.

For that, you need a commit message with a common prefix describing your current activity.
With Git, you can then easily squash all those intermediate commits into one.
See "Trimming GIT Checkins/Squashing GIT History" for more.

VonC
+4  A: 

You should certainly try to avoid comitting code which does not work, and perhaps even does not compile (I think even if you clean up hisory with git rebase --interactive before pushing / publishing code). Otherwise value of git bisect to find bugs would get greatly diminished.

You can use git commit + git commit --amend (or e.g. stg refresh if you use StGIT patch management interface1) to snapshot your code without introducing commits with non-working core.

The rule of thumb is that commit should do one thing, do it well, and do it completely.


Footnotes

1. Or equivalent for other patch management interfaces, like Guilt for Git, or Mercurial Queues (mq) extension distributed with Mercurial, which was inspiration for Guilt.

Jakub Narębski
@Jakub. I agree with that principle behind a commit. Just a minor point: May be you could add the link to StackedGit: http://www.procode.org/stgit/, and to the `stg` man page: http://www.procode.org/stgit/doc/stg.html, including the `stg-refresh` command: http://www.procode.org/stgit/doc/stg-refresh.html
VonC
That sounds interesting (stg). Do you happen to know if there's anything similar for mercurial?
blockhead
@blockhead: all of the Git patch management solutions (Stacked Git, TopGit, Guilt, Git Queues) are more or less directly inspired (if not plain copied) by Mercurial Queues.
Jörg W Mittag
+2  A: 

I use the awesome git-wip tool for users of git and emacs. It makes a commit each time I save, but it makes the commit in a side branch. The automatic commits don't become a part of the history on the main branch and consequently are normally not propagated to other repositories.

It lets met look back through my previous saves easily, but without cluttering my regular branch with non-working commits. Best of both worlds.

Daniel Stutzbach
Once you merge back to your main master branch, you'd have those commits no? Or do you squash them before doing so?
Noufal Ibrahim
@Noufal: There's no merge back. The side branch created by git-wip gets abandoned. For example, if my most recent regular commit is named `A` and I save a file, git-wip will create a branch named `wip/A` and commit the change there. It switches back to my regular branch so I can completely forget that I'm using git-wip.
Daniel Stutzbach
Ah okay. So it maintains a parallel branch and you can do your work as usual just ignoring it. Interesting. Thanks for this. +1. :)
Noufal Ibrahim