Feature branch is prefixed with issue number. eg. PROJ-1234-update-ui-to-do-something. That ensures that every commit is logged against an issue.
If you list --first-parent and show the list of merge commits, you see a list of features which were implemented into the dev branch.
If you need to drill down into lower level changes of a feature, you can look at the individual commits that were made in that branch.
That way merge commits are atomic commits of features, and commits in a branch are logical commits/steps for an individual feature.
And in answer to the original post - I try to make all commits have a message of what was the type of change, what the change was, and where it was. eg. "Added a clear button to reset all form elements on the update address page". The general rule is, you should be able to read the commit message and know exactly what was changed and where. Compared to "Added clear button".