Git-cliff – Generate changelog files from the Git history
github.com
github.com
I've been considering switching to a changelog generator, either from Conventional Commits or from a folder of files just to avoid merge conflicts with the CHANGELOG file.
If people want enforcement of Conventional Commit, check out https://github.com/crate-ci/committed
The real problem is that commit messages and a changelog serve 2 different purposes and have different audiences. Changelog exists to explain what happened with the product, and commit messages exist to explain what happened with the code. These are the same thing only in the most basic situations, like "change Delete button color to red" (and then you probably don't even want to clutter your changelog with such bullshit at all). So, this works when 1 Jira ticket equals 1 commit. This is not usually the case, and, what's more, this usually shouldn't be the case.
If your changelog audience is a project manager, for example, you are better off with generating if from ticket ids that you include into the commits that resolve some task (you don't need and probably don't want that atrocity of "conventional commits" for that). Changelog generated from "conventional commits" is verbose, clunky, sometimes outright false, misses most of important stuff if some things are resolved in libraries. It is simply bad. But arguably better than nothing if there are no tradeoffs. But there are.
The real problem is, now your commits are bad as well, because they are completely fucked up in an attempt to shape them into a changelog, which cannot be done effectively. Best case scenario, your commits now completely mirror your tickets and you end up with huge commits, but at least the changelog looks OK-ish. So the tool intended for developers no more is. Anything in between and both your commits and your changelog are messed up.
I faced this on a small team that adopted it. From my reading, it's OK if you create some of your own prefixes that suit your workflow. The point is to get everyone to use the same thing, not to try to say "feat/chore/etc" are the only things you can ever use. But... the team I was on didn't want to change anything, just use out of the box defaults, because "these are the community standards" (words to that effect).
I do not like being forced in to the "conventional commit" style as it gives the impression that it's providing something of value, when, in our case, it's not really valuable to anyone on the team. I did some other work in 2019 on a different team which was much more efficient and effective with their commits, review, merging, etc, but didn't use conventional commit.
At least you know which commits caused a breaking change compared to spelunking the history to figure out how a library broke compatibility and how you need to adapt to it. Breaking changes are honestly one of the main reasons I read changelogs.
> The real problem is that commit messages and a changelog serve 2 different purposes and have different audiences. Changelog exists to explain what happened with the product, and commit messages exist to explain what happened with the code.
imo a commit summary and the start of the body should explain the the goal, the user facing aspect and then should dig down into the whats and whys of how the changed lines support that goal, using Inverted Pyramid / Bottom-line Up Front writing style.
Of course, if the commit has no end-user impact, you signify that with the type (feat/fix/etc vs chore/style/etc)
While doing a hand-curated changelog for end-users would be more polished, the summary of a commit message should still be passable.
<type>[optional scope]: <description>
fix:
feat:
build:
chore:
ci:
docs:
style:
refactor:
perf:
test:
etc.
Let's say we have following scopes: core, infra, api, runtime. The add label in Github issues for each of them.I do semi-manually generate the ChangeLog using the titles of the Story/Bug that was merged in for a given PR, and then any commits that were done directly get a special notation (if any exist). The list of Stories/Bugs is generated automatically (branch->PR->Story).
This way there is no ever growing file, but the ChangeLog is available for every release within the VCS, and it's organized by release.
I think this relies on you following conventions for commit messages. There could be be an interesting usecase for something like GTP-3 here: I'd love to not have to think too hard about carefully writing parsable commit messages but still be able have something scan my commit log, understand context and create a summarized changelog from it
One downside is that we run into trouble with GitHub API rate-limiting.
[1]: https://github.com/github-changelog-generator/github-changel...
Also I'd like to add to my original comment above: I don't care at all that this is implemented in Rust. Good on you. Open source software goes where the developers go, and isn't dictated by anything except what the developers want to do.
Also I am not bothered by it; I personally find it interesting when a tool is implemented in a language that I find interesting. If it's a language I don't care about, I shrug and move on.
Are you bothered when somebody says "implemented in C 99"?
If you're at the point of looking at the source code, The language used for implementation might actually be relevant to you, when making a choice about whether to use a piece of software or library.
Library - yes, of course it matters what it's written in when I'm choosing it. Software - no, not really, as long as it does what it's supposed to do, C, C++, go, erlang, java, kotlin, python, julia, rust or brainfuck for all I care - sure, god speed.
Ironically, I felt this was your strongest argument because I am bothered when someone says that... like, I am first bothered that someone thinks the language their tool is written in is a selling point, but then I am additionally bothered (even somewhat enraged) that anyone considers their project being written in C99 (and not at least C++, and even explicitly so) to be a selling point!
Like, whenever I see "implemented in C99" I tend to be able to very quickly find a few buffer overflows or memory leaks as it is so hard to dot all your eyes and cross all your tees manually in every single function (with the consequent annoyance that I say the code is likely buggy, get challenged to find a bug, find multiple sometimes only even a few minutes later, and then the goal posts shift to "well we fixed the bugs you found, so we're fine")... and so I guess "implemented in Rust" us at least telling me the code that implemented the tool I am about to use is more likely to be correct? ;P
> so I guess "implemented in Rust" us at least telling me the code that implemented the tool I am about to use is more likely to be correct?
This was my point! It's information for potential consumers, that might or might not be interesting or relevant to you.
Also some people just like talking about how they did something, not just what they did. Maybe they're proud to show it off or they want to let people know about whatever cool thing they like.
not sure what you mean by “auto generated message” - “squash” during interactive rebase will by default ask you to edit the commit message before generating the commit, prefilled with concatenation of messages of all the squashed commits.
Anyone who cares about others reading the commit history, should.
I like the prepend mode a lot, because I would like to write proper release notes above the autogenerated changes. Machines are only so good at this stuff. I think everyone should use these things in prepend mode.
I am not personally a big fan of conventional-commits, mostly because you can never edit the message if you mess it up, and I am more of a ten-commits-at-a-time person so it's hard to remember. I guess you can put it on a (PR) merge commit. But I also think there's a lot of value in scooping up data from the GitHub API, like github_changelog_generator does. Listing closed issues by whether they were closed in the time between tags is fantastic, it's like if you'd been using milestones all along. This would be a great addition to git-cliff: `--issues` to parse commit messages for GitHub-style issue-closing directives ("fixes #24") and build a list of closed issues to link or render freestanding. Same goes for "Merge pull request #25 from ...".
We have a monorepo with a dozen different products, supporting four rolling release series at any time. Some code is shared between products. So having a commit that contains the release note is very convenient. It’ll automatically follow merges, both when merging up bug fixes through all the release branches and merging in features.
When it’s time to build release notes, simply walk the new commits since last release and extract each release note.
Note, I’m leaving out most details on exactly how we have this setup. It’s not that complicated though.
I act like this on public and private repositories.
I know others I have worked with have benefited from and appreciated my detailed commit messages, and I’ve even thereby convinced some to write at least three or four decent lines rather than just one bad line.
I myself have certainly benefited from the verbose commit messages that my past self has written.
But here’s the real secret to it: I have benefited by writing these verbose commit messages, even in cases where it’s unlikely anyone (including me!) will ever read them again. You know rubber ducking <https://en.wikipedia.org/wiki/Rubber_duck_debugging>? Commit messages are about describing what you’ve done and why, and the act of writing that down helps you to think about it. More than a few times have I felt the need to justify the approach taken in a commit message, only to realise as I explain it that I had neglected some key consideration so that the approach I used wouldn’t handle certain corner cases, or that a better technique was possible.
I also write changelogs manually, because commit messages and changelogs have somewhat different purposes. And that helps, too, especially in case of deprecation or breaking change, where the changelog should ideally guide the reader in what they should change.
———
¹ Prominent likely exceptions are found in new projects where I’m doing a bit of everything in an unstructured fashion, and commits on my website repository that just add a new article.
Did the dependency upgrade just improve performance? fix a bug? Add a new capability? Remove a backward compatible feature?
Certainly doesn’t automatically follow that if a dependency upgrade adds a feature, that that is a feature addition in your code, because you haven’t changed your code to use the new feature. But it could be - if you upgraded a parser library so it now supports strings longer than 4K, maybe your component now supports strings longer than 4K too and that merits a minor version bump.
It can be a pretty subtle judgement - especially with potentially deep dependency trees like are common in node.
If you’re bumping a dependency because the dependency has bumped one of its dependencies… can be tricky to figure out if there’s actually a noticeable effect.
build(poetry): update alembic dependency to 1.7.0
build: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
so using build for things that affect /src seems wrong.
I always used to be scared of compiling software myself because I never seemed to be able to get it to work without endless headaches. Now, I generally find it easy to compile Rust programs if they aren't in my package manager, and with cargo install-update https://github.com/nabijaczleweli/cargo-update I find it easy to keep the software up to date. I have higher confidence that I can get hobbyist Rust software working, and the more Rust software I use, the more familiar I am with the ecosystem and the more comfortable I am.
If this was written in some obscure language I wasn't familiar with, I'd be less confident I would be able to run it at all, let alone keep it updated, and I may not bother even trying to install it.