Chapter 11Lesson 01~140 minutes

Tags, Releases, Release Notes, Assets, Changelogs, and Release Governance: Concepts, Architecture, and Mental Model

Separate Git refs from GitHub Release objects, then connect version identity, notes, assets, provenance, support lines, and rollback expectations into one release-governance model.

Git tagsGitHub ReleasesRelease assetsGovernance

Learning objectives

  • Distinguish a Git tag/ref from a GitHub Release database object and release page.
  • Explain draft, prerelease, latest, tag target, release-branch, and support-line relationships without treating them as Git primitives.
  • Separate generated source archives from manually uploaded release assets and identify which evidence belongs to each.
  • Explain generated/manual release notes, comparison ranges, changelog categories, and why labels influence generated notes.
  • Distinguish social immutability from GitHub immutable-release enforcement and understand the associated release attestation.
  • Inspect tags and releases read-only before creating or changing them.
Availability: Releases and tags used in the mandatory path work with a GitHub Free public personal repository. Anyone with read access can view releases; collaborators/people with write access can manage them. Immutable releases are an optional production-strength control; the disposable mandatory lab leaves them disabled so tags/assets can be removed during cleanup.

1. The practical problem: a version name is not enough

A deployment pipeline, a user downloading a binary, and an operator deciding whether to roll back all need the same answer: what exact source state and artifact does this version name identify? Git gives you refs and objects; GitHub adds a release object, notes, downloadable assets, visibility, and governance around a tag. Confusing those layers creates releases whose labels look authoritative while their commit or artifact identity is ambiguous.

Chapter 10 treated protected refs as change-control boundaries. Chapter 11 applies the same evidence-first thinking to the point where a tested commit becomes a named software version consumed by other people or systems.

2. Three identities must agree: commit, tag, and Release

A Git tag is a Git ref under refs/tags/.... An annotated tag also has a tag object containing a message, tagger metadata, and optionally a cryptographic signature. A GitHub Release is hosted metadata associated with a tag: a title, body, draft/prerelease/latest state, timestamps, uploaded assets, links, and API identity. A release is therefore based on a tag, but it is not the tag itself.

Layer Example Source of truth
Commit 8f3… Exact source tree/history identity
Git tag refs/tags/v1.4.0 Named Git reference; annotated tags can carry message/signature
GitHub Release Release ID + tag_name=v1.4.0 Hosted distribution metadata and assets
Uploaded asset app-v1.4.0.zip + SHA-256 Built deliverable; should have independent digest/provenance
Version identity chain
flowchart TD
    C[Commit SHA] -- pointed to by --> T[Git tag v1.4.0]
    T -- selected by --> R[GitHub Release object]
    R -- describes --> N[Release notes]
    R -- distributes --> A[Uploaded assets]
    T -- snapshots --> S[GitHub-generated source ZIP/TAR]
    A -- verify with --> D[Digest / attestation]

Every arrow is a claim you should verify. The release page cannot repair a tag that points at the wrong commit; a correct tag does not prove that an uploaded binary was built from it.

3. Draft, prerelease, and latest are release-object states

Draft means the Release object is not yet published. Drafts are useful for assembling notes and assets before the release becomes visible as a normal published release. Prerelease marks a published release as not yet suitable for general production use. Latest is a GitHub designation used for the repository’s current full release; drafts and prereleases cannot be the latest release through the current REST model.

Do not confuse “latest” with “greatest commit on main.” A release can target an older commit intentionally, and support branches may publish versions after newer development has continued elsewhere.

4. Tag target, release branch, and support line are different relationships

A release ultimately keys off a tag. If you run gh release create for a tag that does not exist, GitHub CLI can create that tag from the default branch or from --target. In a governed process, prefer creating and inspecting the tag explicitly, then use --verify-tag so release creation fails rather than silently inventing a tag at an unintended commit.

A branch such as release/1.x is a support line, not a release identity. You might cut v1.4.1 from that branch while main develops v2.0. The tag freezes the version identity; the branch remains movable development state.

5. Release notes are an operational interface, not decoration

Manual notes let maintainers explain upgrades, risks, migrations, known issues, rollback steps, and support implications. GitHub can also automatically generate notes from merged pull requests, contributors, and configured categories. A .github/release.yml file can group or exclude changes using PR labels and authors.

Generated notes are only as useful as the metadata feeding them. If teams label PRs inconsistently, generated notes can omit or misclassify important changes. Always review generated output before publishing.

6. Uploaded assets and generated source archives have different provenance

GitHub automatically offers ZIP and tar.gz source archives corresponding to the tag. These archives are generated from repository content; they are not the same thing as a CI-built binary you manually upload. Uploaded assets are separate release-asset records with names, sizes, download counts, and—through the current REST schema—a digest field.

The distinction matters for reproducibility. A source archive proves what repository snapshot was packaged by GitHub; it does not prove that app.exe or container.tar was built from that snapshot with a particular toolchain. Keep build provenance and hashes with the uploaded artifact.

7. Treat published versions as immutable—even when the platform would let you edit them

Without enforcement, Git lets an authorized actor move or delete tags and GitHub lets release managers replace assets. A disciplined release process still treats a published version name as immutable: corrections become a new version rather than silently changing what an existing version means.

GitHub now offers immutable releases. When enabled, a published release locks its associated tag and uploaded assets; GitHub also generates a release attestation containing the release tag, commit SHA, and assets. Drafts remain editable until publication. If an immutable release is deleted, the tag may then be deleted, but the same immutable-release tag name cannot be reused.

# Production verification after publishing an immutable release
gh release verify v1.4.0
gh release verify-asset v1.4.0 ./dist/app-v1.4.0.zip

gh release verify-asset validates the local asset digest against the release attestation. It does not apply to GitHub-generated source ZIP/tar archives, which are produced when requested rather than stored as uploaded release assets.

Production pattern: create a draft → attach/finalize every asset → inspect hashes/notes/target → publish → verify the immutable release/asset attestation. The mandatory disposable lab does not enable immutability because cleanup intentionally deletes its releases and tags.

8. Read-only inspection before release mutation

# Local/remote tag state
git tag --list --sort=-version:refname
git ls-remote --tags origin

# Hosted Release state
gh release list -R OWNER/REPO --json tagName,name,isDraft,isPrerelease,isLatest,isImmutable,publishedAt

# Versioned REST: Release records are distinct from regular tags
gh api -H "Accept: application/vnd.github+json" \
  -H "X-GitHub-Api-Version: 2026-03-10" \
  repos/OWNER/REPO/releases --paginate

# Inspect one tag target locally
git rev-list -n 1 v1.4.0

If a tag appears in git ls-remote --tags but not in the Releases API list, that is not an inconsistency: a regular tag does not automatically have a GitHub Release object.

9. DevOps connection: a Release is a supply-chain boundary

CI may produce an artifact; a GitHub Release decides how a version, notes, source snapshot, and uploaded assets are presented to consumers. Release governance must therefore answer: which commit is this, what was built, how was it verified, who may publish, which support line owns it, what does “latest” mean, and what happens when it is bad?

10. Lesson summary

Tags are Git refs; Releases are GitHub objects associated with tags. Draft/prerelease/latest are hosted release states. Source archives are generated repository snapshots, while uploaded assets are independent deliverables that need hashes/provenance. Generated notes depend on pull-request metadata. Production releases should be treated as immutable, and GitHub immutable releases can enforce that expectation.

Knowledge check

A tag exists on GitHub but gh release list does not show it. Is the tag broken?

Why should a governed release use gh release create --verify-tag?

Is GitHub’s automatically generated source ZIP the same provenance object as a CI-built binary asset?

What changes when immutable releases are enabled?

Why can generated release notes still be incomplete even when generation succeeds?

Next lesson

Next: Tags, Releases, Release Notes, Assets, Changelogs, and Release Governance: Guided Hands-On Workflow and Core Operations

Further reading — current official GitHub sources

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.