Section 4 · Professional Habits
Commit Messages, Tags and Releases
15 min3 min readSpot the bug
Lesson at a glance
Write commit messages that explain why, follow the Conventional Commits format when a team uses it, mark versions with annotated tags, and publish a GitHub Release with generated notes.
No video here — just the real thing: a written lesson, runnable examples, a quiz and practice.
Six months from now you’ll run git log on your portfolio looking for when the dark theme broke, and you’ll be reading messages written by past you. “updates”, “fix”, “asdf” won’t help. History is only as useful as the words attached to it. This lesson is about making those words count, and then about naming the moments that matter: versions.
What a good commit message looks like
A commit message has a subject line, a blank line, and an optional body:
Fix footer overlapping content on mobile
The footer used position: fixed, so on screens shorter than
the content it covered the last project card. Switch to a
normal flow footer and add bottom padding to the grid.
Closes #13The conventions, and why they exist:
- Subject under about 50 characters. It’s what
git log --oneline, GitHub’s commit lists and pull request titles show; long ones get cut off. - Imperative mood: “Fix”, “Add”, “Remove”, not “Fixed” or “Adds”. A handy test: the subject completes “If applied, this commit will…”. It also matches the messages Git writes itself, like “Merge branch ‘footer’”.
- No full stop at the end of the subject.
- The body explains why, wrapped at about 72 characters. The diff already shows what changed; only you know the reason, the alternative you rejected, the bug it fixes.
- Trailers go at the bottom:
Closes #13, orCo-authored-by: Name <email>, which GitHub uses to credit pair-programming partners.
Use git commit without -m when a change needs a body; your editor makes multi-line messages easy. For one-line changes, -m is fine.
Conventional Commits
Many teams adopt a structured format called Conventional Commits:
feat(projects): add tag filter to projects page
fix(nav): close mobile menu when a link is clicked
docs: add setup steps to README
ci: run HTML check on pull requests
feat!: rename data-theme attribute to data-color-schemeThe shape is type(optional scope): description. The specification defines feat (a new feature) and fix (a bug fix); teams commonly add docs, style (formatting only, not CSS), refactor, perf, test, build, ci and chore. A ! before the colon, or a BREAKING CHANGE: footer, marks a change that breaks existing users.
The payoff is automation. Because the type is machine-readable, tools can generate changelogs and choose the next semantic version for you: fix bumps the patch number (1.4.2 to 1.4.3), feat the minor (1.5.0), a breaking change the major (2.0.0).
Conventional Commits usually keeps the description lowercase, which differs from the capitalised style above. Neither is wrong. Use what the repository already uses; consistency beats preference. For your portfolio, try Conventional Commits; it’s common enough on teams that the habit pays off.
Tags: naming a moment
Branches move; tags don’t. A tag is a permanent name for one commit, used to mark versions: the portfolio as it was at launch, at v1.1, and so on.
Git has two kinds. A lightweight tag is just a name pointing at a commit. An annotated tag is a full object with the tagger’s name, a date and a message. Use annotated tags for releases:
git tag -a v1.0.0 -m "Portfolio launch"
git tag # list tags
git show v1.0.0 # tag message, then the commit it points at
git tag -a v0.9.0 b2e04f3 -m "Preview for mentors" # tag an older commitTags stay on your machine until you push them, which surprises almost everyone the first time:
git push origin v1.0.0 # one tag
git push --follow-tags # commits plus any annotated tags that point at themTreat a pushed tag as permanent. If you tagged the wrong commit and already pushed it, publish a new version (v1.0.1) rather than moving v1.0.0 under people who may have used it.
GitHub Releases
A release on GitHub is a tag plus a title, notes and optional downloadable files. Open your repository’s Releases page, choose Draft a new release, pick the tag (or create one), and click Generate release notes: GitHub lists the pull requests merged since the previous release, with their authors. Edit the notes into something a human wants to read, then publish.
The CLI does the same in one line:
gh release create v1.0.0 --title "Portfolio v1.0.0" --generate-notesGood pull request titles become good release notes for free, one more reason the earlier habits pay off.
Clean messages, tags and releases make history readable. The final step is making main trustworthy without having to watch it yourself: automated checks on every pull request, and rules that enforce them.
Key takeaways
- A good subject line is short, imperative and specific (“Fix footer overlap on mobile”); the body, after a blank line, explains why.
- Conventional Commits prefix the subject with a type such as
feat,fixordocs, which lets tools derive version numbers and changelogs. - Annotated tags (
git tag -a v1.0.0 -m "…") record who tagged what and when; they’re the right kind for releases. git pushdoesn’t send tags; push them withgit push origin v1.0.0orgit push --follow-tags.- A GitHub Release is a tag plus notes and optional files, and GitHub can generate the notes from merged pull requests.