back

by jasonpeacock·4y ago·view on hn ↗
This is a good idea, but in practice after a few commits you learn all the principles and don't need a wall of text in your commit template. Getting feedback in your PRs about your commit messages helps quickly reinforce learning these best practices. (you do review the commit message when doing PRs, right? ;)

I'm a big fan of Conventional Commits[1], so my commit template reminds me of the types and provides an actual template to describe my change:

    <type>(optional scope):
    # type: build ci chore docs feat fix perf refactor revert style test
 
    Problem:
 
    Solution:
 
    Testing:
 
    Issue:
Where Problem describes why this change is needed, Solution is what this change delivers, and Testing is how this change was validated. Issue is the JIRA/Github issue related to this change.

EDIT: The Problem/Solution/Testing/Issue is not part of Conventional Commits, I added those to give structure to the body.

[1] https://www.conventionalcommits.org/en/v1.0.0/

7 comments
I've always seen conventional commits as an anti-pattern as it seems to discourage developers from writing small, atomic commits.

I think that a commit should always be as small as possible and have a descriptive, meaningful message. It is therefore pretty common that I end up with tens of commits when working on a simple feature. Which of these commits should be labelled as "feat" when the feature is added by a group of commits rather than a specific one, and that none of them really adds any feature? Also, a bug can be fixed by many commits. Which of these commits should be labeled as "fix"? We can't label all of them as fixes as cherry-picking only one of them wouldn't fix anything, which means the commit message would be misleading. The only solution left is to create one commit per bug fix or per feature.

Moreover, this information can (and should) be carried by the branch name already, as you'd usually branch off from your main branch to either fix a bug or develop a new feature. All you have to do is to follow a naming convention for your branch like "feature/my-awesome-feature" or "bugfix/fix-this-annoying-bug".

The only benefit I see with using conventional commits is generating changelogs automatically from your git history.

Conventional Commits restricts each commit to a single type of change - no mixing bug fixes, features, and refactoring. This supports exactly what you want - small, atomic commits.

Why can't each small change be labeled "feat"? A feature does not need to be contained in a single change as a "big bang" commit. I make multiple "feat" changes to deliver a feature.

I follow trunk-based development[1], so branches are many, transient, and disposable (and sometimes not even present if it's a small change I'm pushing straight to `main`).

The advantage of Conventional Commits is that I can go to my trunk (`main`), and scroll through the list of commits and see their purpose at a glance:

    feat: ...
    feat: ...
    build: ...
    fix: ...
    feat: ...
    chore: ...
I can immediately tell which changes were related to fixing the build, or a bug, or supported feature development.

[1] https://trunkbaseddevelopment.com/

I nearly never look at individual commits in a PR.

I realize that this isn't applicable to all codebases, but when troubleshooting why a bug happens, or was intended to work, I find it a lot easier to look at a squashed commit than at the individual commits that went into a pull request. It does make `git bisect` less specific (and, to my shame, I've never used it), but having an overall commit message + pull request that points at a Jira ticket (or similar) helps identify whether something was intended behavior or not, and I've never felt the need to look deeper at whether part of it was a refactor/chore/feature. (If I had, I could look at the PR branch, presumably.)

In contrast, I've often had a stream of a 12-20 commits with tiny atomic (and often terrible) messages like "bugfix", "add test", "fix test", "fix linting", which I then try to rebase into some _coherent_ messaging of the time you espouse, where linting + typo fixes are rearranged and squashed on top of the commits that added them, and tests + features are added more closely together. It's very satisfying to do this, but in retrospect I've always felt like the time I spent doing that has been wasted --- it's hard, and often involves many iterations of conflict resolution when reordering commits, all for something that I or my team will squash anyway. The benefit gained (more readable commits of temporary value) never ever seems worth the time (Multiple hours) put into making them that way.

> I've always seen conventional commits as an anti-pattern as it seems to discourage developers from writing small, atomic commits.

Me too, actually I hate conventional commits with a pattern, because I have never seen a "conventional commit message" that actually does a good job. I've recently even written a short article on that subject (https://news.ycombinator.com/item?id=29924976) because it is so annoying to me that people think writing a "conventional commit message" alone results in better quality (hint: it does not).

I’m a big fan of Conventional Commits specification too. I always been strict with myself when writing commit messages, but I have members of my team that were a mess. So, it’s good for establishing a clear pattern for everyone to follow. Also, by implementing it, you gain a lot of flexibility in terms of the interaction of your code being pushed and the CI/CD pipeline. (e.g auto release generation with semver)

The only “bad” thing is that I feel some of the <type> standards don’t fit very well for certain cases that are not exactly distributable software. (In my case, devops, committing to a TF project we own: mmmm is this a “chore”, a “feat” etc)

I also like the problem/solution format, it gives a ton of context.
Please - be aware of what you're doing relying on conventional commits. I saw projects using them to later do automatic merges between branches, and I think this is the "wrong level of abstraction". I think there is an underlying problem if you are mixing "fix" and "feature" (for example) commits in a "feature" branch. Why the fix is in a feature branch? I think it's more important to have the distintion on a "branch" level, linked in a 1-1 relation to a jira/feature/bugtracker issue and whatnot.
Now you're talking about branching strategies, not commits, which is a different and much larger topic :)

I keep it simple - branches are short-lived. I don't even like feature branches, I break features into a series of changes and push each change to `main`, incrementally delivering all the changes needed to make the feature useful while keeping `main` healthy.

More details at: https://trunkbaseddevelopment.com/

I hadn't seen Conventional Commits; my in-head template looks very similar, with the addition of a "Situation" before the "Problem". On a big project, the reviewer may not know (or may not remember off-hand) exactly what the code does at the moment. So saying, "The code currently does X" is a helpful prompt, so that when they read "That's a problem because of Y", they have all the key context in their head (rather than perhaps having to guess and/or look at the code to figure out what's going on).
We have a:

What

Why

How

Related

isn't the problem described in the jira ticket?
> isn't the problem described in the jira ticket?

Yes/perhaps/maybe, but it's nice to (a) have it in front of you without having to change programs or context, and/or (b) have it summarized, as the ticket may have 'extraneous' stuff like a bunch of back-and-forth with the user/client/tester/etc.

Organizations ought to preserve tickets across migrations to new systems, but they don’t always. Only commits are forever.
Except tons of orgs squash before merge (unfortunately, IMHO) so individual commits are pretty transitory. Doing “conventional commits” for all those smaller commits seems wasteful.
They often believe they'll never change ticket systems. Until they find out one morning IT didn't subscribe to the same ideology.
Nice to have the problem in line because I can search git history. Also no guarantees that the Jira ticket will be around as long as the code.
The problem the commit is addressing might not be exactly the same as the problem in the JIRA ticket (e.g. you're solving a bigger problem than just what the JIRA describes, or there are multiple causes and this commit fixes only one of them, etc).