Stop trusting LLMs to write your release notes. They hallucinate features that never shipped. A new deterministic changelog generator takes a different approach: it diffs two commits and emits a structured changelog without touching the history with a model. But when developer imapphelp ran it on a real repo with 214 commits, the output was a mess. It listed a feature added and then removed in the same release, creating a 'phone book' of noise that lied about the destination.
The Merge Commit Noise Problem
The first hurdle was sheer volume. In the v1.3 to v1.4 range, 96 of the 214 commits were merges. In squash-merge workflows, these are useless because the squashed commit already holds the PR title and description. The developer implemented git log --no-merges to cut the list down to 118 items. However, they added a caveat: 'evil merges' that introduce changes not present in any parent are kept visible. The tool only suppresses merges matching recognizable templates, ensuring that oddballs don't disappear into the void.
When Reverts Break the Narrative
The real failure happened in a v2.1 changelog. The tool faithfully listed 'Added CSV export' and, further down, 'Removed CSV export'. Both commits were real and within range. A reviewer had caught a data-loss bug after the initial commit, leading to a revert. The net change to the artifact was zero, but the changelog described the journey, not the destination. This highlighted a fundamental truth: commit history is a lossy proxy for release contents. A changelog must be a statement about the artifact at the endpoints, not the road between them.
The Pairing Algorithm
To fix this, the generator now scans for Revert " commits and GitHub-style revert bodies. It pairs these against their original commits within the same range. If an exact pair is found, both are dropped from the main list and surfaced only as a 'suppressed-changes' note. This ensures the changelog reflects the final state. However, partial revertsβsuch as a feature reverted and then reworked, or a revert-with-editsβcannot be safely paired. These remain flagged as 'unstable' during the window, preventing the tool from making confident claims about changes that aren't fully netted out.
Key Takeaways
- Commit history is evidence, not the verdict; treat it as a witness to the final artifact state.
- Deterministic diffing beats LLM generation for accuracy, as models often invent features from context.
- Partial reverts must remain visible to avoid hiding instability or complex change histories.
- The tool is available as a small API at x402.freeq.one/tools/changelog_git.html.
The Bottom Line
If your release notes don't reflect the net state of the artifact, they are misleading documentation. Deterministic diffing is the only way to ensure accuracy in a world of noisy commit histories.