Following my previous post Git is cheap I'd like to add a bit more about the missing part of it : git rebase.
Committing early and branching often is a good approach, but as many comments on the HN post and on the article point it : it's not enough.
Once you start to commit early, branch often (CeBo ?) you'll find that you tend to have lots of commits, especially if you follow a TDD approach such as : write failing test, make the test pass, commit, refactor the code, commit.
In all cases if you end up with many small commits changing the same lines. The best approach (to keep sane and a clean code base) is to rebase those commits together.
We are not talking about the merge vs rebase thing here : we are talking about the rebase -i command and its awesome fixup and squash options.
When doing a git rebase -i you need to specify a reference point (usually HEAD) and a quantity of commits to go through :
> git rebase -i HEAD~3 # will rebase 3 commits from HEAD
Then you will be presented with a list of those 3 commits and the commands you can apply on them : edit, reword, squash, fixup, pick :
- pick : just keep the commit as is
- edit : allow you to edit (amend) the commit
- squash : merge the commit with the one preceding it (the one above), the log message will be merged with the previous commit's one
- fixup : merge the commit with the previous one, the message will be discarded
For this post we are mostly interested by squash and its, somehow rougher, counterpart : fixup. Those two commands will allow you to bring two or more commits together in a single one. Hence if you have refactored one or more times the same piece of code you'll only keep the result of your last commit. This will make your commit history more readable and easier to follow : after all, you didn't change the behaviour, only the form, or did you ?
Beware of the fact that rebase -i will change commit history, and this is bad if you have pushed those rebased commits to a remote repository. You should check Linus Torvalds' email about merging and rebasing to understand this important part of Git's usage. Yet to put it shortly : never rewrite published or publicly available commits.
You can also check this great article about rewriting history : http://git-scm.com/book/en/Git-Tools-Rewriting-History.
commit early, branch often ... rebase nicely