skip to content

Releases and Packages

Turning a tag into something consumable: a release with generated notes and attached artifacts, and packages pushed to GitHub's npm, Maven, NuGet or container registries. The interview angle is automation — releases cut by a workflow on tag, not by hand.

part ofGitHuboverview, primer and where to startread it →
on this pageshow

questions

5

In GitHub, what does a release add on top of the Git tag it points at?

level: juniorimportance: must knowfreq 58%

answer

  1. One layer is Git, one is the platform
  2. Ask what a clone brings with it
  3. Files, not just a pointer
  4. Creating it can create the tag
  5. Deleting it leaves the tag behind

basics

~20 s

A GitHub release is a platform object wrapped around a tag: it adds a title, release notes, uploadable binary assets, draft and prerelease flags, a stable download URL, and API and feed access. The tag itself stays a plain Git pointer.

solid answer

~40 s

A tag is Git: a name for a commit, and nothing more. A **GitHub release** is a separate object on GitHub that *references* a tag (`tag_name`) and adds everything a consumer needs: a human title, a Markdown body for the notes, **release assets** you upload — the built binaries, checksums, signatures — plus `draft`, `prerelease` and latest flags, and auto-generated source archives in zip and tarball form. It has its own REST representation under `/repos/{owner}/{repo}/releases`, an Atom feed at `/releases.atom`, and it can notify watchers. Two practical consequences: creating a release can create the tag if it does not exist yet, and deleting the release leaves the tag behind. Everything the release adds is GitHub-side — clone the repository elsewhere and you get the tags, never the notes or the assets.

code

json · 12 lines
json
{
  "tag_name": "v2.5.0",
  "target_commitish": "main",
  "name": "v2.5.0",
  "body": "## What's changed\n* Rewrote refresh-token handling",
  "draft": false,
  "prerelease": false,
  "assets": [
    { "name": "api-service-2.5.0.jar", "size": 41283910 },
    { "name": "api-service-2.5.0.jar.sha256", "size": 96 }
  ]
}

go deeper

for a junior

Be able to say that a GitHub release wraps a Git tag with a title, notes and downloadable files, and that the tag alone carries none of that.

for a middle

Explain the object: tag_name and target_commitish, uploaded assets versus generated source archives, and that release data lives on GitHub rather than in the Git object database.

for a senior

Draw the portability and distribution consequences — what a mirror loses, why binaries and checksums belong in assets, and why a release is not a substitute for publishing to a registry.

for a principal

Decide what role releases play in your distribution story at all: which audiences read them, what must be reproducible from them, and what has to exist elsewhere because it cannot depend on one vendor's records.

## Two different layers A **tag** is a Git object: a name pointing at a commit, replicated by anyone who clones or fetches it. Git knows nothing about titles, notes, downloads or publication states. A **GitHub release** is a record in GitHub's database that references a tag by name and carries the human and distribution layer around it. The two are linked but independent: the tag can exist with no release, and deleting a release does not delete the tag. ## What the release object holds - **`tag_name`** — the tag it points at. If that tag does not exist when the release is created, GitHub creates it, at the commit named by **`target_commitish`** (a branch or SHA). This is why you can cut a release entirely through the UI or API without touching a local clone. - **`name`** — the display title, typically the version, often the same as the tag but free to be more human (`v2.5.0 — auth rewrite`). - **`body`** — the release notes in Markdown. Hand-written, generated, or both. - **Assets** — uploaded files: compiled binaries, a jar, a `.tar.gz`, a checksum file, a signature. These are what most consumers actually download, and each gets a stable URL. - **Auto-generated source archives** — GitHub always offers the source at that tag as zip and tar.gz. They are produced on request rather than stored, so if you need byte-stable checksums, publish your own artifact and its checksum file as assets rather than relying on the generated archives. - **`draft`**, **`prerelease`**, and the latest marker — publication state, covered in depth by the flags themselves. - **`created_at` / `published_at`**, the author, and an optional linked discussion. ## Why the distinction is asked Because it is the cleanest test of whether someone understands what is Git and what is GitHub. A candidate who says "a release is just a tag with a nice page" has half of it; the half they are missing is **assets**, and assets are the entire reason releases exist for a distributed binary. A tag lets you check out source. A release lets someone who has never cloned the repository download a signed binary from a stable URL. The portability consequence follows directly: mirror the repository to another host and you take the commits and tags with you. The notes, the assets, the download counts and the publication state stay behind, because they were never in the object database. If a release is part of your distribution story, its data lives in GitHub and needs to be exported deliberately if it must survive a move. ## How a release is created Three routes, all equivalent in what they produce: - The web UI's *Draft a new release* form. - `POST /repos/{owner}/{repo}/releases` with `tag_name` and friends, then a separate upload call per asset. - The `gh release create` command, which wraps the same API and takes asset paths as arguments. The API route is what a workflow uses when a tag push should cut the release automatically, which is the shape most teams end up with. ## Consumption side Several things read releases without a human: - `GET /repos/{owner}/{repo}/releases/latest` returns the current latest release — the standard way an installer script finds "the newest stable version" without hard-coding one. - The Atom feed at `https://github.com/{owner}/{repo}/releases.atom` lets people follow versions without watching the whole repository. - Watching a repository with the *Releases* option notifies on publication, which is how downstream teams learn a version exists. ## What a release is not It is not a package registry entry. Publishing a release does not make `npm install`, a Maven coordinate, or a `docker pull` work — those come from publishing to a registry, which is a separate act. A release is a *versioned announcement with files attached*; a registry is a resolvable dependency source. Mature projects usually do both: the registry serves build tools, the release serves humans, changelog readers, and anyone downloading a binary directly.

  • You mirror the repository to another host. What of the release survives?
    The commits and the tags, because those are Git objects that travel with a clone. The title, notes, uploaded assets, publication flags and download counts are GitHub-side records and stay behind. If releases are part of how you distribute, export them through the API deliberately rather than assuming a mirror covers it.
  • Can you create a GitHub release for a tag that does not exist yet?
    Yes. Supply `tag_name` plus `target_commitish` — a branch name or commit SHA — and GitHub creates the tag at that commit as part of creating the release. It is convenient for UI-driven releases, though most automated pipelines push the tag first and let the workflow react to it.
  • Does publishing a GitHub release make the version installable by a package manager?
    No. A release is a versioned announcement with files attached; it does not register a coordinate any build tool resolves. Making `npm install`, a Maven dependency or a container pull work requires publishing to the corresponding registry, which is a separate step most projects run from the same pipeline.

saying these in an interview costs you the question

  • Says a release is just a prettier view of a tag
  • Expects release assets to arrive with a git clone
  • Thinks deleting a release deletes the tag
  • Assumes a release publishes the package to a registry
  • Relies on generated source archives for stable checksums

context

open as a page

In a GitHub release, what do the draft, prerelease, and latest flags control?

level: middleimportance: should knowfreq 42%

basics

~20 s

Draft keeps a GitHub release private to users with push access and does not create its tag until published. Prerelease publishes it but marks it unstable and excludes it from Latest. The latest marker controls which single release the Latest badge and endpoint resolve to.

open as a page

In GitHub, how do you control what automatically generated release notes contain?

level: middleimportance: should knowfreq 44%

basics

~20 s

Ask GitHub to generate notes (generate_release_notes on the API, --generate-notes on the CLI) and shape the output with a .github/release.yml file, whose changelog block groups merged pull requests into categories by label and excludes chosen labels or authors.

open as a page

A GitHub release v1.2.0 shipped a broken artifact — do you retag it or ship v1.2.1?

level: seniorimportance: should knowfreq 34%

basics

~20 s

Ship v1.2.1. A published version is a fact other people have already fetched and cached, so replacing its contents makes two different artifacts share one name. Burn the bad version, mark it clearly, and move Latest to the good one.

open as a page

How do you cut a GitHub release automatically when a version tag is pushed?

level: seniorimportance: should knowfreq 48%

basics

~20 s

Trigger a workflow on pushes of tags matching your version pattern, grant it contents: write, build the artifacts, then create the release from the pushed tag with generated notes and upload the artifacts as assets before publishing.

open as a page