This guide details best practices for writing Git commit messages, leveraging principles from the Conventional Commits specification.
1. Structure of a commit message
A Git commit message typically comprises three main parts: the header, the body, and the footer. The header is mandatory and includes the type of change, the scope of the change (optional), and a short description. The body is optional and provides detailed information about the change. The footer is also optional and includes additional metadata, such as related issues and breaking changes.
Header format:
<type>(<scope>): <description>
Example:
feat(database): add retry logic to data fetch
2. Types of commits
Conventional Commits defines several types of changes:
- feat: Introduces a new feature.
- fix: Patches a bug.
- docs: Documentation-only changes.
- style: Changes that do not affect the meaning of the code (white-space, formatting, etc).
- refactor: A code change that neither fixes a bug nor adds a feature.
- perf: Improves performance.
- test: Adds missing tests or corrects existing tests.
- chore: Changes to the build process or auxiliary tools and libraries such as documentation generation.
3. Scope (Optional)
The scope provides additional contextual information on where the change has taken effect. For example, it might refer to a particular component or feature that the change impacts.
Example:
fix(parser): handle unexpected end-of-file error
4. Description
The description succinctly summarizes the change in a way that makes the commit message stand alone from other content. It should be imperative, stating what the commit does rather than what it did.
Bad Example:
Fixed bug with Y
Good Example:
Fix bug with Y
5. Body (Optional)
The body should include a detailed explanation of the change, including its rationale and any implications it may have. It is separated from the header by a blank line and wrapped at 72 characters to improve readability.
Example:
fix: handle errors in the protocolEnsure that errors close the socket and reinitialize the connection,preventing the client from hanging in an unstable state.
6. Footer (Optional)
The footer is used for metadata about the commit, such as related issue trackers and breaking changes. Use keywords like Fixes
, Resolves
, or BREAKING CHANGE:
followed by a colon and a space.
Example of Breaking Change:
BREAKING CHANGE: env vars now take precedence over config files.
7. Examples of Commit Messages
Simple fix with description:
Terminalfix: correct minor typos in codeFeature with scope and description:
Terminalfeat(parser): add support for async functionsCommit with multi-paragraph body and multiple footers:
Terminalfeat: unify exception handlingCreate a new exception handler that deals with all error cases in a unified manner. This change simplifies the control flow and makes error handling more predictable.Reviewed-by: ZRefs: #123
8. Why Use Conventional Commits?
- Automated Changelog Generation: Helps generate a structured changelog from commit history.
- Semantic Versioning: Automatically determines a semantic version bump based on the types of commits.
- Improved Collaboration: Makes it easier for team members to understand the nature of changes, facilitating quicker reviews and collaborative development.
Conclusion
Adhering to a standardized commit message format, like Conventional Commits, significantly benefits project management and developer communication. By clearly describing your changes with an appropriate type, scope, and detailed description, you contribute to a clear, navigable, and useful commit history.