Skip to content
masterclass Buddy

Git · Command

git rev-parse

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

How it works

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.

Syntax

git rev-parse [<options>] <arg>…

Parameters

NameTypeDescription
<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}.
--verifyflagRequires exactly one argument that resolves to an object name. It prints that name, or fails.
-q / --quietflagUsed with --verify. If the name is invalid, it exits with a non-zero status and prints no error message.
--short[=<length>]flagWorks like --verify but prints a unique abbreviated object name, with a minimum length of 4.
--abbrev-ref[=(strict|loose)]flagPrints a short ref name that is not ambiguous, such as the current branch name for HEAD.
--symbolic-full-nameflagPrints refs as full refnames, such as refs/heads/main, and leaves out any input that is not a ref.
--show-toplevel / --show-prefix / --show-cdupflagReport 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>flagFind the repository directory, or a file inside it, while respecting relocation variables and worktrees.
--is-inside-work-tree / --is-bare-repository / --is-shallow-repositoryflagEach prints true or false for its check.
--parseopt / --sq-quoteflagSpecial operation modes for parsing options in shell scripts and for quoting arguments for the shell. They must come first.

Returns

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.

Key points

  • Its original job is to split a mixed command line into flags, revision arguments for rev-list, and everything else. The filtering options --revs-only, --no-revs, --flags and --no-flags control which of these groups get printed.
  • --verify is the safe way to resolve one name to an object ID. Pass exactly one argument; anything else is an error. Adding a peel such as ^{commit} also makes sure the object exists and has the type you expect.
  • --short gives an abbreviated hash that is still unique. If you don't pass a length, it uses core.abbrev.
  • --abbrev-ref HEAD is the usual way to print the name of the current branch rather than its commit hash.
  • Scripts can find out where they are running. --show-toplevel gives the absolute path of the work tree root, and --show-prefix gives the current directory's path relative to that root.
  • The --is-* options print true or false. Use them in scripts to check the current environment, for example whether you are inside a work tree or whether the repository is bare or shallow.
  • Use --git-path when you need the location of a file inside the repository directory. It takes relocation variables and linked worktrees into account, so it is safer than building $GIT_DIR/... paths yourself.
  • --disambiguate=<prefix> lists every object whose name starts with a short hex prefix, which shows why a short hash is ambiguous. The prefix has a minimum length.

Common mistakes

  • If the name comes from user input, put --end-of-options before it. Otherwise an input like --all would be read as an option instead of a revision.
  • --parseopt and --sq-quote are operation modes and only work when placed before every other option.
  • Date and count reflog suffixes such as main@{yesterday} or main@{1} read the local reflog. They fail if the ref has no reflog, for example right after a fresh clone.
  • Most modes need a repository and stop with a fatal error outside one. Only a few, such as --parseopt and --sq-quote, are documented as working anywhere.

Example: Gather repo context safely in a shell script

#!/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.

When to use it

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.

Validating input in Git hooks and tools

A hook gets a revision argument and checks it with --verify --end-of-options "$REV^{commit}" before running any destructive step.

Making scripts location-independent

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.

Writing Git-style option parsing in shell

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.

Interview questions

QIn a script, how do you reliably get the commit hash that a user-provided revision points to?

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.

QHow would you get the current branch name and its upstream with rev-parse?

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.

QWhy use git rev-parse --git-path instead of building paths like .git/hooks or .git/HEAD yourself?

--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-list
  • gitrevisions
  • git show-ref
  • git symbolic-ref
  • git describe
  • git merge-base
  • git for-each-ref
  • git update-ref

Source: Git - git-rev-parse Documentation. Checked 2026-11-02.