Skip to content
Git Basics: Describe a Commit Relative to a Release Tag

Git Basics: Describe a Commit Relative to a Release Tag

October 27, 2026

A build report often needs a readable relationship to the last release. git describe finds a reachable tag and can add commit distance and an abbreviated object name. This fixture checks that relationship without printing a date-dependent commit hash.

Prepare a scratch directory

Tested on Linux with Git 2.52.0 and GNU Bash 5.2.37. You need the named runtime, Bash, a text editor, and the standard mktemp, rm, and rmdir utilities. The script creates a second temporary fixture directory and removes only that directory through its exit trap. Run it in a normal Bash terminal, outside any Git hook or Git wrapper. No global Git configuration is changed.

Keep using the same terminal. Stop if setup fails, before saving the source:

start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 1

Run the example

Save this as demonstrate-describe.sh:

#!/usr/bin/env bash
set -euo pipefail
export LC_ALL=C
fixture_dir="$(mktemp -d)"
trap 'rm -rf -- "$fixture_dir"' EXIT
export GIT_CONFIG_NOSYSTEM=1
export GIT_CONFIG_GLOBAL=/dev/null
unset GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE
git init -q -b main "$fixture_dir/repo"
cd -- "$fixture_dir/repo"
git config user.name 'Practice Author'
git config user.email 'practice@example.invalid'
printf 'first\n' > app.txt
git add app.txt
git commit -qm 'First version'
git tag -a v1.0 -m 'Version one'
printf 'Exact tag: %s\n' "$(git describe --exact-match HEAD)"
printf 'second\n' >> app.txt
git commit -qam 'One change after release'
description="$(git describe --long --abbrev=7 HEAD)"
case "$description" in v1.0-1-g*) ;; *) exit 1 ;; esac
printf 'Nearest tag: %s\n' "$(git describe --abbrev=0 HEAD)"
printf 'Distance from tag: %s\n' "$(git rev-list --count v1.0..HEAD)"
printf 'Long description has tag-distance-hash form: yes\n'
printf 'local change\n' >> app.txt
dirty="$(git describe --dirty)"
case "$dirty" in *-dirty) printf 'Tracked working edit marked dirty: yes\n' ;; *) exit 1 ;; esac

Run it:

bash demonstrate-describe.sh

Observed output:

Exact tag: v1.0
Nearest tag: v1.0
Distance from tag: 1
Long description has tag-distance-hash form: yes
Tracked working edit marked dirty: yes

Read the result

The annotated tag names the first commit exactly. One commit later, the long description contains the tag, a distance of one, and a g-prefixed abbreviation. The script validates that shape but omits the changing hash from the displayed output. The final invocation marks an uncommitted tracked-file edit with the dirty suffix.

Apply it carefully

By default, describe considers annotated tags; --tags also considers lightweight tags. A shallow clone or missing tags can change the result or make description fail. The result is a useful build label, not a semantic-version parser or proof that a release was published. The dirty suffix does not inventory every untracked artifact, and an abbreviated hash should not be treated as a permanent unique identifier across arbitrary repositories.

The official reference describes the API and its options. The checks above cover the specific fixture, not every possible input or environment.

Clean up

Remove the source and then the empty practice directory:

rm -- demonstrate-describe.sh
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dir

If the directory is not empty, inspect the remaining files rather than deleting unknown contents.

Acknowledgements

This post was created with assistance from AI.

Last updated on