Stamping builds with a commit ID
A CI job or release script runs rev-parse --short HEAD and embeds the result in an artifact name or version string.
Git · Command
git rev-parse is a low-level plumbing command. It turns revision expressions such as HEAD~2 or v1.0^{commit} into object names, and it can also report details about the repository, such as its top-level path, whether you are inside a work tree, and the current branch.
Last updated
git rev-parse takes a list of arguments and works out which ones are flags, which are revisions meant for git rev-list, and which are something else. It prints each result on its own line. Revisions are resolved with the extended SHA-1 syntax, which covers refs, reflog suffixes like @{n}, ancestry operators like ^ and ~, peeling like ^{type}, and paths like rev:path. Other options switch it into helper roles. It can report repository facts such as paths and booleans, quote arguments for the shell (--sq-quote), or parse script options (--parseopt). Most modes must run inside a repository.
git rev-parse [<options>] <arg>…| Name | Type | Description |
|---|---|---|
<arg>… | string(s) | The flags and parameters to parse. Revisions use the extended SHA-1 syntax, for example HEAD, main~3, v1.0^{commit}, or @{u}. |
--verify | flag | Requires exactly one argument that resolves to an object name. It prints that name, or fails. |
-q / --quiet | flag | Used with --verify. If the name is invalid, it exits with a non-zero status and prints no error message. |
--short[=<length>] | flag | Works like --verify but prints a unique abbreviated object name, with a minimum length of 4. |
--abbrev-ref[=(strict|loose)] | flag | Prints a short ref name that is not ambiguous, such as the current branch name for HEAD. |
--symbolic-full-name | flag | Prints refs as full refnames, such as refs/heads/main, and leaves out any input that is not a ref. |
--show-toplevel / --show-prefix / --show-cdup | flag | Report where you are in the working tree: the path of its root, your current directory relative to the root, and the relative path back up to the root. |
--git-dir / --absolute-git-dir / --git-path <path> | flag | Find the repository directory, or a file inside it, while respecting relocation variables and worktrees. |
--is-inside-work-tree / --is-bare-repository / --is-shallow-repository | flag | Each prints true or false for its check. |
--parseopt / --sq-quote | flag | Special operation modes for parsing options in shell scripts and for quoting arguments for the shell. They must come first. |
Writes its results to standard output, usually one line per item: object names, ref names, paths, or true/false. On failure it exits with a non-zero status. In --parseopt mode a usage error exits with code 129.
#!/usr/bin/env bash
set -euo pipefail
# Bail out early if not inside a work tree
if [ "$(git rev-parse --is-inside-work-tree 2>/dev/null)" != "true" ]; then
echo "not in a git work tree" >&2
exit 1
fi
root=$(git rev-parse --show-toplevel)
branch=$(git rev-parse --abbrev-ref HEAD)
sha=$(git rev-parse --verify HEAD)
short=$(git rev-parse --short HEAD)
# Validate a user-supplied revision as a commit, quietly
rev="${1:-main}"
if commit=$(git rev-parse --quiet --verify --end-of-options "${rev}^{commit}"); then
echo "$rev -> $commit"
else
echo "'$rev' is not a commit" >&2
fi
# Upstream of the current branch, as a full ref (may be unset)
upstream=$(git rev-parse --symbolic-full-name @{u} 2>/dev/null || echo none)
echo "root=$root branch=$branch sha=$sha short=$short upstream=$upstream"This script first checks that it is running inside a work tree. It then reads the repository root, the current branch, and the HEAD hash, checks that a revision given by the user names a commit, and looks up the branch's upstream.
A CI job or release script runs rev-parse --short HEAD and embeds the result in an artifact name or version string.
A hook gets a revision argument and checks it with --verify --end-of-options "$REV^{commit}" before running any destructive step.
A helper script can be started from any subdirectory. It changes into the --show-toplevel path and keeps the user's relative file arguments valid by passing them through --prefix.
A custom git-foo shell command describes its options in a spec and passes it to --parseopt. This gives it -h usage output and --no-* negation like built-in Git commands have.
Run git rev-parse --verify --end-of-options "$REV^{commit}". --verify accepts exactly one argument and fails unless it resolves to an object. The ^{commit} suffix peels the object until it reaches a commit, so the command also fails if the name does not point to a commit. Add -q if you want only a non-zero exit status instead of an error message.
Follow-up: Why can git rev-parse v1.0 and git rev-parse v1.0^{commit} print different hashes? For an annotated tag, the plain name resolves to the tag object itself, and peeling with ^{commit} (or ^0) follows it to the commit the tag points at.
git rev-parse --abbrev-ref HEAD prints a short branch name such as main instead of a hash. For the upstream, git rev-parse --symbolic-full-name @{u} prints the remote-tracking ref, for example refs/remotes/origin/main. @{u} is resolved from the branch's configured remote and merge settings.
Follow-up: When does @{push} differ from @{upstream}? It differs in a triangular workflow, where you pull from one remote and push to another, such as when remote.pushdefault points to a fork. In a non-triangular setup the two are the same.
--git-path resolves a path inside $GIT_DIR while taking relocation variables such as $GIT_OBJECT_DIRECTORY and $GIT_INDEX_FILE into account. Hard-coded .git/... paths fail when .git is a gitfile, when GIT_DIR is set, or inside linked worktrees. For the same reason, --git-dir or --absolute-git-dir is the reliable way to find the repository directory itself.
Follow-up: What is the difference between --sq and --sq-quote? --sq still interprets the input as rev-parse arguments and then prints the result as one shell-quoted line. --sq-quote is a separate mode that only quotes its arguments and can run outside a repository.
git rev-listgitrevisionsgit show-refgit symbolic-refgit describegit merge-basegit for-each-refgit update-ref