Make Your Commits Meaningful! A Guide To Conventional Commits

Created Date

19 Feb, 2025

Make Your Commits Meaningful! A Guide To Conventional Commits

Imagine you are working on a large project. During the daily stand-up meeting, your team lead asks, “When was this feature added?” You check the Git history, but the commit messages are a complete mess!

Understanding who changed what and why is nearly impossible! Moreover, for a new team member joining the project, tracking changes through past commits becomes a real struggle. This is exactly where Conventional Commits come into play.

Conventional Commits ensure that commit messages follow a structured format, making the project history more readable and manageable. It allows us to instantly answer the question, “What does this commit do?” at a glance.

Just that? Actually, it is much more than that! Thanks to this standard, we make our commit messages meaningful, optimize versioning processes, generate changelogs effortlessly, and manage CI/CD workflows more effectively.

However, to achieve all of this, we first need to fully understand what Conventional Commits are, how they work, and why we should use them. In this article, we will start with the fundamentals of Conventional Commits, explore different commit types, learn how to use them effectively, and discuss the best usage scenarios. If you want to make commit messages a powerful part of your development process, you’re in the right place! 🚀

What are Conventional Commits?

  • Conventional Commits is a specification that defines a standard format for commit messages.
  • It is compatible with Sementic Versioning (SemVer), making changes easier to understand and enabling automated versioning processes.
  • It allows for automatic versioning, changelog generation, and seamless integration into CI/CD workflows.

Conventional Commits require commit messages to follow a specific structure. The general format is as follows:


<type>(<scope?>): <message>
  

This format consists of three main components:

  1. type: Specifies the type of change made. For example, feat, fix, docs, refactor, etc.
  2. scope (optional): Indicates the module or component affected by the change. If the commit impacts a specific part of the project, it can be mentioned here.
  3. message: A short and concise description of the change made.

This standard ensures that commit messages are meaningful and consistent. As a result, when looking at the commit history, the type of change can be immediately understood. However, the type value used in each commit message is not chosen randomly. The selected commit type should reflect the impact of the change on the project and its relationship with Sementic Versioning (SemVer).

For example, when adding a new feature, we use feat because this change results in a minor version update. For bug fixes, we typically use fix since these changes correspond to a patch-level update. Documentation updates, code refactoring or adding tests do not directly affect the functionality of the application, so they do not impact the version number.

Here are the most commonly used commit types that make our commit messages meaningful, manageable, and aligned with versioning processes:

  1. feat (Adding a new feature) Used when adding a new functionality to the project. This type of commit indicates that the change has a minor impact on the versioning.
  2. fix (Bug fix) Used when fixing a bug. Bug fixes typically result in patch version updates.
  3. docs (Documentation update) Used when making changes only to documentation files (e.g., README.md, API documentation). The code itself does not change; only explanations and descriptions are updated.
  4. style (Code style and formatting) Used for changes that o not affect the functionality of the code but improve its readability and appearance. Examples include adding spaces, changing line breaks, and fixing linter errors.
  5. refactor (Code restructuring) Used for improving the structure of the code without fixing a bug or adding a new feature. The functionality remains the same, but the code organization and quality are enhanced.
  6. perf (Performance improvements) Used when making changes to improve the performance of the application. Optimizations that make the code run faster fall into this category.
  7. test (Adding or updating tests) Used when adding a new test or updating existing ones. These changes do not modify the functionality of code but expand the test coverage.
  8. chore (Project configuration and workflow changes) Used for changes that are not directly related to code or documentation. This includes dependency updates, build configurations, and workflow adjustments.

Conventional Commits help structure commit messages, categorize changes, and make the project more understandable. The type values are chosen based on the nature of the change, and this selection is directly related to the project’s version management. This standard not only organizes our commit messages but also makes it easier to understand the changes made by other developers on the team. As a result, by reviewing the commit history, we can quickly grasp what changes were made, when and why, enabling a more structured and sustainable development process.

📌 Example Commit Messages Following the Conventional Commit Format:

Let’s assume we have added an authentication system that allows users to log in to the project. Since this is a new feature, we need to write a commit using the feat type.


feat(auth): add user authentication feature
  

Or, let’s say the total price of the items in the cart was being miscalculated on the checkout page of our project. We discovered that this issue was caused by incorrect tax calculations and fixed the bug. Since we are fixing an error, the commit type should be fix.


fix(cart): fix price calculation error on the checkout page
  

Another example: A new developer joining the project noticed that the setup instructions in the README.md file were incomplete or incorrect. To improve clarity, you added the missing information and made the documentation more comprehensive. In this case, the commit type should be as fallows:


docs(readme): update project setup instructions on README.md file

Beyond Commit Messages: Strengthening the Software Development Process with Conventional Commits

As we mentioned at the beginning of our article, Conventional Commits is not just a standard for structuring commit messages, it is a powerful tool that makes software development processes more meaningful, manageable, and automated. By enforcing a structured format for commit messages, we can automate versioning, simplify changelog generation, and manage CI/CD workflows more effectively.

This way, each commit does more than modify code—it helps us better understand the progress of the software and ensures seamless version transitions. By clearly distinguishing between new features and bug fixes, we can create a more structured and efficient workflow within the project.

By adding specific type values to commit messages, we can ensure that version numbers are incremented in accordance with Semantic Versioning (SemVer). For example, commits starting with feat trigger minor version updates, while fix commits result in patch updates. If a breaking change (a backward-incompatible modification) is introduced, a major version update is required. This way, instead of managing versioning manually, we can automate version updates based on commit messages.

Having commit messages in a structured format greatly simplifies the changelog generation process. Since each commit type is categorized, there is no need to manually write a changelog. Instead, tools like standard-version or commitizen can automatically generate a changelog based on the commit history. This makes it easier for team members and project users to track the changes made throughout the project.

Conventional Commits not only facilitate versioning and changelog generation but also play a significant role in the CI/CD process. By leveraging commit types, we can trigger specific tests or execute deployments based on the type of commit. For instance, we can configure the system to deploy to the staging environment only when a feat commits is made or run specific test exclusively after fix commits. This approach helps streamline Continuous Integration (CI) and Continuous Deployment (CD) processes, making them more structured and efficient.

Considering all these advantages, Conventional Commits is not just a method for structuring commit messages; it is a powerful approach that makes software development processes more systematic, sustainable, and automated.

In this article, we explored what we can achieve with the Conventional Commits specification. Implementing these methods, which significantly streamline our workflows, in real-world projects is easier than you might think!

Conclusion

In this guide, we explore the power of Conventional Commits and how to go beyond just structuring commit messages to improve software development processes. By following this standard, we:

✅ Ensured commit messages are structured, readable, and meaningful.

✅ Understood the logic behind automated versioning and changelog generation using the Conventional Commit format.

✅ Gained insight into managing CI/CD processes more effectively and designing commit-based automation workflows.

Conventional Commits is not just the best practice —it’s a key tool for making software development more sustainable, collaborative, and automated.

“See you in our next blog post! Wishing you well-structured commits and seamless software development. As the Plaincoder team, we are here to support on your journey in the world of software engineering 🌟”

Launch Your Next Big Idea With Us

Let’s Talk!