Conventional Commits: A specification for structured commit messages(conventionalcommits.org) |
Conventional Commits: A specification for structured commit messages(conventionalcommits.org) |
“Have you linted and unit tested your commit message?”
“Junior Developer wanted. 10 years of Conventional Commits experience required.”
“Download Conventionalizer! Now you can write Conventional Commits in plain English, having all the syntax automatically generated! (node, erlang OTP and Jerry’s pre-alpha TensorFlow binding library required. Windows support coming soon.)”
Something tells me the authors are hard at work solving a problem nobody needs solving.
I share some of your sentiment though: I feel like the biggest reason to enforce a style like this is not for "machine readable commit messages" (I mean, why?), but to encourage people to split refactors and features in separate commits. This makes it easier to understand what's going on later.
I think this site should've begun with that, and left the spec as a footnote.
We use this in our lerna monorepo and it works like a charm as the CI can just bump whatever packages based on the paths and commit messages.
The machine-readable part is useful for generating changelogs (eg. broken out by type) or implementing semver (eg. detecting breaking changes).
instead of 'feat:', why not 'feature:'?
I dislike partial abbreviation because it is confusing; yes doc for document and max for maximum make sense but in this case feat is literally a different word?
Before:
> feat: allow provided config object to extend other configs
After
> Add option for config object to extend other configs
I know this isn't the point of changelogs, but I've been using the verbs from KeepAChangelog to start my commit messages and it's been going well so far.
> Add template preview to status page
> Change textarea to increase height on `:focus`
> Remove deprecated CLI flags
> Fix margin styles causing layout problems
Setting that aside, the conventional commit "standard" (https://xkcd.com/927/) doesn't focus on what I think is the most important aspect of a commit: a good commit subject and message. In fact, prefixing the subject line with certain tags limits the amount of characters you have for writing the message; assuming you want to stick with the usual 50 character limit.
It's pedantic to me. I'm completly fine with terse incomplete sentences. They are not harder to understand. Plus I work with international teams. Terse is often easier to write and understand for non-native speakers.
I like my "Feature" much more than "feat". This is my default commit message that I edit to contain what I want:
<Type>: <Description>
# Type can be:
# - Feature: A new feature
# - Bugfix: A bug fix
# - Docs: Documentation only changes
# - Styling: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
# - Refactor: A code change that neither fixes a bug nor adds a feature
# - Performance: A code change that improves performance
# - Tests: Adding missing tests
# - Chore: Changes to the build process or auxiliary tools and libraries such as documentation generation
From my experience, a few characters less do matter (which is also why I dropped conventional commits and just use "Add blah blah to blah", "Fix typo in user-facing message").
I much prefer encoding structured information like this at the ticket level where history can be more easily corrected and items are expected to be visible for all of time.
https://www.gnu.org/prep/standards/html_node/Change-Logs.htm...
This widely used format gives details about what is being done to each function.
This was designed to be used in a ChangeLog file, so it has to be adopted for repository use. We don't have to record the date and name, since that is in the commit meta-data. WE write a commit title, and then the ChangeLog entry becomes the details placed after the blank line. That entry is mandatory: no title-only commits! There can be one or more discussion paragraphs between the title and the ChangeLog entry. We know that these paragraphs aren't ChangeLog entry material because they don't begin with the asterisk.
Like this: http://www.kylheku.com/cgit/txr/commit/?id=b2739251281d7f6ef...
However, I don't find it that useful in the the final applications, even counter productive, since it typically will take up quite a bit of space in the commit title. Many of our front end devs completely ignore title length conventions now.
I see this in nearly every company I go to - everyone rushing to skip over adding anything useful to the permanent log by using git commit -m rather than a plain got commit.
The main problem is very commit titles that end up looking like:
feat(SomeScope.OtherScope.Class): add support for abc and xyz optionhttps://github.com/probot/semantic-pull-requests
It obviously won't catch your mistake if you forget to mark a breaking change as breaking, but it's a start.
Right now, we are switching SCM's and are looking at adopting Conventional to replace our internal style. I've already started using Conventional and have really appreciated it. It makes it fast and succinct (remember, line length "requirements" in git) to get the information you need even in one-line logs. Also, it makes CHANGELOG maintenance easier, whether using an automated tool or doing it by-hand.
Not happy with the other ones, I've created my own commit style validation tool, committed [0] and have deployed it on my open source projects. Like code style enforcement in CI, I like delegating this to a tool since it makes the requirement very clear for contributors.
The one thing I'm disappointed with with Conventional is that they did not follow git conventions for multi-line trailers.
Haven’t figured out a good way to integrate co-authors easily with it though.
"body", optionally, describes WHY.
Also it feels like more of a convention for a personal project with optional C(I|D) automation prerequisites. In a team there should be a clear and emphasized place for the issue tracking info (ticket number, task id etc etc)
“ The last thing to keep in mind is the commit message. Getting in the habit of creating quality commit messages makes using and collaborating with Git a lot easier. As a general rule, your messages should start with a single line that’s no more than about 50 characters and that describes the changeset concisely, followed by a blank line, followed by a more detailed explanation. The Git project requires that the more detailed explanation include your motivation for the change and contrast its implementation with previous behavior — this is a good guideline to follow. Write your commit message in the imperative: "Fix bug" and not "Fixed bug" or "Fixes bug."”
Similarly there are rare cases where I’ve swept breaking changes under the rug because they were severe bug or security fixes that affected a corner case unlikely to be seen in the wild.
After all the commit message is secondary to the actual code committed.
I'm sure everyone can share an episode when a nicely worded commit had to be followed up with an ugly 'Fix a typo' message.
The most practical convention is the one that's automated to some degree, for example, issue/feature tag auto-linking or some template driven messages. Either way the message should not become an ultimate hoop to jump before the actual commit and one more thing to 'maintain', the code should be the focus.
In my experience, a commit message describing the committed behavior (even when intended) helps tie the code to the overall scope. In case when it's a bugfix, it still must be tied to a correct expected behavior.
So in some sense a commit message could serve as an auxilliary level of unit testing. Of course, I'd rather put an effort to enforce the actual practice of unit testing over structuring the commit messages.
There is `git commit --fixup` and `git rebase -i --autosquash` for that ;)
This actually had me laughing quite a bit. Because of my love for dad jokes, here are some less conventional commits:
"fete" : adding holiday support
"braking change" : a change of pace
"nix" : removing a featute
"suffix" : adding a nice to have
https://github.com/lerna/lerna/blob/master/commands/version/...
They are metadata, and as such they shouldn't take more attention than the actual data.
This matters when you are in a bug hunt in production - you want to find the culprit commit as efficiently as possible, without distractions.
As for easier to read thousands of newspaper headlines and magazine article titles provide strong evidence otherwise. Even HN itself is proof it doesn't matter
It's usual to include the ticket id in the commit or PR so you can pull it from logs at build time and have a canonical list. Then grab the info to include from the ticketing system.
Except when people would literally just mash their keyboard like this:
Commit 1234: iuadiuasdbuidawbiywbuqbqbdfpbdpiube
Patch descriptions are for developers, not for users -- aside from the fact they're the wrong granularity (no user cares if it took 20 patches and three PR cycles to implement a feature), they should contain details and justification that are only useful for future debugging or for review purposes (which users also don't care about). And if you have a bugfix for a previously-merged patch that hasn't yet been released, why would you include the bugfix in the changelog?
Yes, with the right format and discipline you could generate reasonable changelogs from your commit logs -- but at that point it's so much easier to just keep a CHANGELOG.md.
I wish GitHub or Azure DevOps made this configurable (because I use them) - anyone know if any other hosted git systems have this as a configurable option?
Also, in the kernel generally you reference a different commit in a commit message with the form 'commit <12 char commit id> ("subject")'. So further restricting it makes sense.
In any event, I think teams should be free to adopt the workflow that works best for them without tools getting in the way. GitHub wrapping commit messages at 70 chars, even though I have more than plenty enough horizontal real estate, isn't helping anyone.
We can, and do. Knowing that the merges are going to wind up as items in the changelog leads us to size and structure them accordingly, or at least make a best effort to. The end result is a changelog where most PRs are somehow "noteworthy" and the ones that aren't (usually "chore" type in Conventional Commits lingo) can all be grouped together down the tail end.
The point isn't to produce a perfect result, but one that is "good enough". With this system, the friction to produce a new release is so low, and we have so many projects, that we can easily push out a steady stream of releases at very low cost with this approach. And following the pattern across all the projects has been great for consistency, compared to the relative chaos in patterns and procedures that we had before.
Common practice for a long time has been to include a ticket id in the commit and then use a script to pull all the ticket ids from the commits since the last release and pull the (user facing) release note info from ticketing system.
Of course you don't want commit messages going to users but you don't want to rely on handcrafted lists either. Particularly when a release as far as a customer is concerned is infrequent and contains changes from many repos.
It's useful for automatically determining the next semantic release version by inspecting the commit history alone.
fix: <-- patch
feat: <-- minor
breaking: <-- major
Some fixes will require breaking changes. Fixes can be part of the message with the issue #, etc.
In terms of release management, it makes configuring CI jobs simpler with one less parameter. If you automatically release merges to master, you can use standard-version with conventional commit syntax. On other projects, I've seen people use GitHub PR labels to mark 'major', 'minor', or 'patch' releases (the CI system reads this information when generating releases).
If you feel it's inappropriate for this information to live in your commit history, you'll need to specify it through one of these other options.
Since I don't have a dedicated team for this sort of infrastructure (I maintain my own Jenkins jobs), I find that Conventional Commits get the job done, so I can focus on other things. There could be better ways, but I have more pressing problems than demand my attention, with higher priority than optimizing my CICD configurations.
[0]: https://github.com/conventional-changelog/standard-version
People do this? I guess it's fine if your commits are <100 lines of code but it seems needlessly concise, to the point of losing information.
Personally, almost all my commits follow email styling: first line tries to be concise, newline, then a list of what changes have been made along with a brief justification. Feels like a bare minimum unless you'd rather tie everything into pr's (which can't be seen from command line). This is why for people unfamiliar with git I refuse to tell them about commit -m because I feel it leads to undocumented history when you need to audit code.
disclaimer: I tend to work on long lived projects (5+ years)
Edit: bonus point that I forgot - by having a detailed commit log that reads like prose, it's easy to explain "everything you guys are working on" to the non technical folks.
The character limit was only referring to the subject line. Under it you can have as many lines of additional context as you wish. That's the normal way; the subject is brief, the message is arbitrarily long.
For what it's worth, the linux kernel limits it to around 70 chars and uses a subsystem prefix, so clearly that can work on large long-lived complex projects.
Your argument against 50 characters in the entire message, including the body, is not one anyone would ever argue for, so you've constructed a complete strawman.
The code is what actually gets run, sure, but good code with bad or misleading documentation can cause trouble later on. Commit messages are documentation.
"or appends a ! after the type/scope, introduces a breaking API change"