In my experience, a git commit should have the following seven characteristics:
- It has a single purpose.
- It has an adequate commit message.
- It's complete.
- It has a limited scope.
- It gets reviewed.
- It's traceable.
- It can be reverted.
Let's review each points.
When you are working on a new feature you may also find and fix a typo, a small bug or refactor an inconsistency. Resist the temptation to commit changes unrelated to the thing you are working on.
Why not just commit everything? Because it makes the review much harder. When something breaks, it's unclear whether it was caused by the new feature, or the little refactoring you also did.
git add -p to select only the relevant changes. The other changes can be committed, reviewed and deployed separately.
Tell what you did. Be specific. "Minor changes", "bugfix" or "Added test" doesn't cut it. "Fix bug where negative input leads to crash" or "Add option to toggle dark mode" are much better.
Was the feature incomplete? Or did the reviewer point out that a test is missing? If additional work logically still belongs to the previous commit, add it with
git commit --amend.
Don't commit an incomplete feature. All tests should be green. Your commit should leave the system in a consistent state. It should be possible to deploy the system if necessary.
Qualification to the previous rule:
Are you working on a huge feature? Then your reviewer will be overwhelmed by one large commit. Think of a good way to split your work into consistent commits.
Split by layer: first commit the new business logic and then the user interface components. Or split by sub-feature. Whatever works best.
Every commit should get reviewed. Even the small ones. Why? Because reviews are a good way to encourage feedback, catch bugs, to inform team members about changes and to reinforce your team's coding guidelines.
Reference the corresponding Jira/GitHub/... issue in your commit message. This enables you to track the state of a commit in your project management tool of choice.
Of course a commit can be reverted with
git revert. But sometimes, another system's state is changed by your commit. Does your commit include a database migration? Then please also write and test the rollback function.