Tagging Releases Properly in Git

Tagging Releases Properly in Git

21 October 2026 · By Laravel Git · 2 min read

git tag v1.5.0 takes three seconds and produces the weaker of Git’s two tag types. For anything you will deploy, reference in a changelog, or bisect against later, take the extra flag.

Lightweight vs annotated#

A lightweight tag is just a name pointing at a commit - a branch that never moves. An annotated tag is a real Git object: it carries its own message, the tagger’s identity and the date:

git tag -a v1.5.0 -m "v1.5.0: invoice PDFs, queue retry fix"

That message is the difference. Six months from now, git show v1.5.0 on an annotated tag tells you what the release was; on a lightweight one it shows whatever commit happened to be tagged, with no context.

Tag what you deploy#

The tag should mark the commit that actually went out. On a merge-based flow that is the merge commit on main - not the last feature commit on the branch, and not “roughly that week”. Tagging anything else makes git bisect between releases and git log v1.4.0..v1.5.0 quietly wrong, and those two commands are the whole point of having tags.

Push them deliberately#

Tags do not travel with ordinary pushes:

git push origin v1.5.0

Push the one tag by name. git push --tags sends every local tag, including the throwaway markers you made for yourself - keep that one for the rare day you actually mean it.

Optional: signed tags#

git tag -s signs the tag with your key, so the release record is verifiable as yours. For a small team shipping to their own server it is usually more ceremony than threat model; for anything customers or auditors pull, it is the same calculation as signing commits - cheap with SSH keys, worth it when provenance matters.

Annotated tags plus the changelog habit are the whole release ritual: the tag marks what shipped and says it in a sentence, the log between tags writes the notes, and git bisect between two tags finds the commit that broke the build.

Share this post

Our network