CyberHuginn

Home

/

Notes

/

why-i-switched-to-conventional-git-commit-messages

Why I Switched to Conventional Git Commit Messages

Why I switched from inconsistent Git commit messages to a Conventional Commits style, with practical examples for cleaner and more maintainable Git history.

Git

Tip

Aug 9, 2026 · 3 min read

Why I Switched to Conventional Git Commit Messages

For a long time, I didn't really have a consistent pattern for writing Git commit messages.

My commits were usually something like:

update user model
fix login
changes
final changes
fix bug
update
new changes

They worked, but after a while, looking through the Git history became painful.

I couldn't immediately understand what each commit was about, whether it introduced a new feature, fixed a bug, changed the architecture, or was simply a configuration change.

As my projects became larger, especially backend projects with Django and multiple services, I started using a more structured Git commit message convention based on Conventional Commits.

The pattern is simple:

<type>: <description>

I currently use these commit types:

  • feat: → a new feature
  • fix: → a bug fix
  • refactor: → restructuring without changing behavior
  • docs: → documentation changes
  • test: → adding or updating tests
  • chore: → maintenance work such as configuration or dependencies
  • perf: → performance improvements
  • style: → formatting or linting changes

For example:

feat: add accounts app
feat: add user registration
feat: add email authentication
feat: add team management
feat: add project monitoring
fix: handle duplicate email registration
refactor: improve user authentication flow
chore: update project dependencies
docs: update authentication documentation
test: add accounts app tests

Why I Prefer This Pattern

The biggest benefit is that a Git history becomes readable.

When I look at a project months later, I don't have to open every commit to understand what happened. The commit type already gives me context.

feat:     something new was added
fix:      something was broken and got fixed
refactor: the code changed, but behavior didn't
chore:    project maintenance

It also makes commits easier to search and filter. If I want to see all new features, I can look for feat:. If I'm investigating bugs, I can focus on fix: commits.

More importantly, it forces me to think about what kind of change I'm actually making before committing it.

A commit message like:

update stuff

doesn't tell me much.

But:

refactor: simplify authentication flow

immediately tells me what happened.

I don't think a commit convention needs to be complicated. The goal is not to write perfect commit messages. The goal is to make the history of a project understandable.

For me, this small change made Git history much cleaner and easier to maintain, so this is the pattern I use now for my projects.

Related Notes

The API Worked. The Architecture Didn’t.

A practical look at why a working API does not always mean a healthy architecture, covering coupling, synchronous work, database bottlenecks, caching, microservices, failure modes, and the importance of clear boundaries.

When Redis Is Not the Solution

Redis is fast and extremely useful, but that doesn't make it the right solution for every backend problem. A practical look at when Redis helps with caching, rate limiting, OTPs, locks, queues, sessions, and temporary data—and when it simply adds unnecessary infrastructure and complexity.

Django Transactions: What atomic() Actually Protects

Learn how Django transactions work, what transaction.atomic() actually protects, and how to handle race conditions, row locking, database constraints, nested transactions, and post-commit side effects with select_for_update() and on_commit().

The Hidden Cost of Django REST Framework Serializers

Learn how Django REST Framework serializers can cause N+1 queries, slow API responses, and unnecessary database work—and how to optimize them with select_related, prefetch_related, annotations, and better serializer design.

Building a Django Package — Part 4: Publishing django-healthkit to PyPI

In this final part, we prepare django-healthkit for release, build and validate the package, test it on TestPyPI, publish it to PyPI, and create a Git tag and GitHub release.

Building a Django Package — Part 3: Health Check Manager and Endpoint

In Part 3, we connect the database and cache health checks, build the health check manager, expose a Django health endpoint, measure check latency, and return a structured health status.

Building a Django Package — Part 2: Database and Cache Health Checks

In this part, we implement the first health checks for django-healthkit, covering database connectivity and Django cache functionality with simple, independent, and testable checks.

Building a Django Package — Part 1: Setting Up django-healthkit

In this part, we build the initial structure of django-healthkit, configure the package with pyproject.toml, and prepare it for development.

Building a Secure Webhook Receiver for Server-to-Server Communication

How I built a secure FastAPI webhook receiver using RSA signatures to enable authenticated server-to-server communication, proxy requests, and connect applications across different network environments.

Building django-healthkit

How a simple health endpoint for Bidar turned into django-healthkit, a lightweight Django health-check package.

Designing a Gold Jewelry E-Commerce Database with Django

Learn how to design a scalable Django database for a gold jewelry e-commerce platform by modeling products, attributes, and purchasable product variants using real-world domain-driven design principles.

How to Fix Common Next.js 16 Build Errors (Proxy, Dynamic Rendering & Revalidation)

Learn how to fix common Next.js 16 build errors, understand Proxy, Dynamic Rendering, and Revalidation, and improve your application's SEO and performance.

Why I Built cyber-ui: A Minimal Design System for Developers

How my projects, from backend systems to monitoring tools, led me to create a minimal and personal UI foundation.

End of note.