Tags (The Bookmarks)
What is the difference between a Commit and a Tag?
A Commit is an actual point in history with a long, unreadable hash (like a1b2c3d4...). Humans are terrible at memorizing hashes. A Tag is simply a human-readable alias or "Bookmark" (like v1.0). It allows you to say git checkout v1.0 instead of memorizing 40 random characters.
Two Types of Tags
If tags are just bookmarks pointing to commits, how are they stored?
A Lightweight tag is just a text file. It literally just contains the commit hash. It is the exact same thing as a branch, but it never moves forward when you write new code.
An Annotated tag, however, is a massive, permanent Git Object stored in the database alongside your blobs and trees! It contains its own message, its own timestamp, and its own author metadata, and then points downwards to the commit.
Interacting with the Timeline
In the interactive simulation above, try adding a Lightweight tag. Notice how it acts as a simple sticky note directly on the exact commit hash.
Now add an Annotated tag. It spawns an entirely separated box hovering above the timeline! This visualizes perfectly that an annotated tag is an independent Git Object that contains its own metadata, and maps downward to the protected commit.
Pro-Tip for Releases
Because annotated tags actually store who made the tag and when, they are the strictly enforced standard for creating software releases (like v1.0.0). Lightweight tags are generally only used for temporary personal bookmarks.
Proving the Architecture
If you run cat-file -p on a lightweight tag, Git just prints out the commit contents directly, because a lightweight tag is literally just a string pointing to the commit. But if you run it on an Annotated tag, you get to see the actual Tag Object architecture: