As developers, we spend a significant amount of time writing code. But how much thought do we put into our commit messages? Good commit messages are crucial for maintaining a clean and understandable Git history. Enter Conventional Commits, a specification for adding human and machine-readable meaning to commit messages.
Why Conventional Commits?
- Automatic versioning: Tools can automatically determine the next semantic version based on the types of commits.
- Automatic changelog generation: With structured commit messages, generating changelogs becomes a breeze.
- Easier to understand: Team members can quickly grasp the nature of changes without diving into the code.
- Better organization: Commits are naturally categorized, making it easier to navigate project history.
The Structure
A conventional commit message has the following structure:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
Let's break this down:
Types
The type
field describes the nature of the change. Common types include:
-
feat
: A new feature -
fix
: A bug fix -
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
: A code change that improves performance -
test
: Adding missing tests or correcting existing tests -
build
: Changes that affect the build system or external dependencies -
ci
: Changes to our CI configuration files and scripts
Scope
The scope
is optional and provides additional contextual information. For example:
feat(auth): add login functionality
Here, auth
is the scope, indicating that this feature is related to authentication.
Description
The description is a short summary of the code changes. It should be written in the imperative mood, as if you're giving a command. For example:
- "add login functionality" (not "added" or "adding")
- "fix race condition in data processing" (not "fixed" or "fixing")
Body
The body is optional and can be used to provide more detailed explanatory text. It should be separated from the description by a blank line.
Footer
The footer is optional and is used to reference issue tracker IDs or provide additional metadata.
Examples
Let's look at some examples of conventional commit messages:
feat: add user registration functionality
Implement a new user registration form and backend logic to create new user accounts.
Closes #123
fix(database): resolve connection timeout issue
Increase database connection timeout from 5s to 15s to account for network latency.
This change should reduce the number of failed database connections during peak hours.
docs: update README with new build instructions
- Add section on environment setup
- Update outdated CLI commands
- Include troubleshooting tips
refactor!: change API endpoint structure
BREAKING CHANGE: The API endpoint structure has been completely revamped.
Clients will need to update their API calls to match the new structure.
Old structure: /api/v1/users/get
New structure: /api/v2/users
Note the use of !
and BREAKING CHANGE:
in the last example. This indicates a breaking change, which is crucial for semantic versioning.
Implementing in Your Workflow
Team Agreement: Discuss and agree on the commit convention with your team.
Git Hooks: Use tools like Husky to set up Git hooks that validate commit messages.
IDE Integration: Many IDEs have plugins that support conventional commits. For example, VS Code has the "Conventional Commits" extension.
Commit CLI: Use tools like
commitizen
to guide you through writing conventional commits:
npm install -g commitizen
commitizen init cz-conventional-changelog --save-dev --save-exact
Then, use git cz
instead of git commit
to commit your changes.
- Automation: Set up tools to automate versioning and changelog generation based on your commits.
Benefits in Action
Let's see how these structured commits can be used:
-
Generating Changelogs: Tools like
standard-version
can automatically generate changelogs:
npx standard-version
- Filtering Commits: You can easily filter commits by type:
git log --oneline --grep "^feat"
-
Semantic Versioning: Tools can determine the next version based on commit types. For example, a
fix
might bump the patch version, while afeat
bumps the minor version.
Conclusion
Adopting conventional commits might seem like a small change, but it can significantly improve your project's maintainability and collaboration efficiency. By providing a clear structure for commit messages, you're not just documenting changes – you're building a roadmap of your project's evolution.
Remember, the goal is clear communication. While following the convention is important, the most crucial aspect is conveying the essence of your changes effectively to your team and your future self.
Have you used conventional commits in your projects? What has been your experience? Share your thoughts and tips in the comments below!
Top comments (0)