TL;DR : committing and branching is cheap with git so stop worrying about it : split your features into small bricks and commit early and often.
Git is a wonderful tool, yet many of us use it like a glorified svn. Git is not only about features but also about flows and we should pay more attention to that when learning or teaching about git.
Git is a distributed version control software, with git it's cheap to create commits or branches :
- committing/branching does not require an access to a central server
- committing/branching does not directly impact other developers
- committing/branching take few seconds to happen
- merging and diffing commits/branches is very fast
As I told a young developer recently : stop worrying about finishing this or that before committing, just commit as soon as you pass a step. Of course it's nice to finish a whole feature before committing or making a new branch but it will make this far more difficult at medium and long term when other developers (or yourself) will look back, make some diffs, patches, proposes changes etc ...
So we arrive at the important point : commit early, branch often.
Young or messy developers (like me) tend to rush into writing code to implement feature X or Y; this is a very bad habit. It's ok to do so if you just want to test and verify an idea but you should just dump that code once you are done with that test.
Once you know where to go you need to break down the feature you want to add into very little bricks. Each brick needs to be the smallest possible : one or two (unit or integration) tests to add to describe the brick, and the corresponding one or two methods to write (or change) to make them pass.
Group the bricks by dependence from one to another, if you have 10 bricks to do, with about 10 to 20 tests and methods to write and all them are "dependent" upon one another you might have to go back to the white board and think again.
Grouping two or three bricks is probably ok, ten is not, ten is starting to be a lot of code to wrap the mind around.
Each group of bricks will become a topic branch, since each group does not depend on another one you can branch of master or whatever pre production branch your team is working on.
This will make the development process faster : you can push topic branches early since they are smaller, your fellow developers can check them out earlier, comment them, and accept the pull requests earlier too. Because they are small it takes them less than a pomodoro to check each one, so it does not interrupt too much their own rhythm.
You might not end the day with the whole feature in the main branch but already part of it is in, it's been commented, improved and approved by others and possibly, it triggered some refactoring in other developers work.
The point behind all this is to get code shipped fast. In 2012, by 15th of August GitHub has had 2300+ production deploys (since 1st January), with an average of 10 per day ! That's the way to go : for each deploy there was probably several pull requests and merges involved upstream so you can imagine the rhythm it implies.
Short commits are easier to read and wrap the mind around, so are small topic branches (5 commits or less). It helps to get code checked, commented, improved and shipped fast.
Remember : Smaller commits and branches also imply less complexity in the code which means less bugs.
commit early, branch often.
To get a broader view about code quality you should check this talk by Brandon Keepers (GitHub) : https://speakerdeck.com/u/bkeepers/p/why-our-code-smells.