Skip to content

rev-parse Git Command Guide

The git rev-parse command picks out and massages parameters, primarily used to parse revision names and convert them to SHA-1 hashes. It can also provide information about the repository state and is essential for Git scripting and automation.

Terminal window
git rev-parse [<options>] <arg>...
ModeDescription
--parseoptUse option parsing mode
--sq-quoteUse single-quote mode for shell
--notNegate revisions
--verifyVerify revisions exist
--quietSuppress error messages
--shortShow short SHA-1
--abbrev-refShow abbreviated ref name
OptionDescription
--git-dirShow .git directory path
--is-inside-git-dirCheck if inside .git directory
--is-inside-work-treeCheck if inside work tree
--is-bare-repositoryCheck if repository is bare
--local-env-varsShow local environment variables
--show-cdupShow path to repository root
--show-prefixShow path from repository root
--show-toplevelShow top-level directory
OptionDescription
--revs-onlyShow only revision arguments
--no-revsShow only non-revision arguments
--flagsShow parsed flags
--no-flagsShow non-flag arguments
--default <ref>Default revision if none given
--prefix <dir>Prepend prefix to arguments
--resolve-git-dir <path>Resolve .git directory path
OptionDescription
--symbolicShow symbolic refs
--symbolic-full-nameShow full symbolic names
--disambiguate=<prefix>Disambiguate truncated SHA-1
--allShow all refs
--branchesShow branch refs
--tagsShow tag refs
--remotesShow remote refs
ParameterDescription
<arg>Revisions, refs, or paths to parse
<prefix>Path prefix for resolution
<ref>Default reference
Common Revision Formats:
├── SHA-1: Full or abbreviated commit hash
├── Branch: main, develop, feature/branch
├── Tag: v1.0.0, stable
├── Relative: HEAD~1, HEAD^2, HEAD@{1}
├── Range: main..feature, main...develop
└── Symbolic: HEAD, ORIG_HEAD, MERGE_HEAD
Resolution Process:
1. Parse revision specifier
2. Resolve to full SHA-1 hash
3. Validate object exists
4. Return canonical form
Repository State Queries:
├── git rev-parse --git-dir # .git directory path
├── git rev-parse --is-inside-work-tree # In work tree?
├── git rev-parse --show-toplevel # Repository root
├── git rev-parse --show-prefix # Current subdirectory
├── git rev-parse --show-cdup # Path to root
└── git rev-parse --is-bare-repository # Bare repository?
Reference Types:
├── Branches: refs/heads/main
├── Tags: refs/tags/v1.0
├── Remotes: refs/remotes/origin/main
├── Stash: refs/stash
├── Special: HEAD, ORIG_HEAD, MERGE_HEAD
└── Reflog: HEAD@{1}, main@{yesterday}
Terminal window
# Get full SHA-1 for HEAD
git rev-parse HEAD
# Get abbreviated SHA-1
git rev-parse --short HEAD
# Resolve branch to SHA-1
git rev-parse main
# Resolve tag to SHA-1
git rev-parse v1.0.0
# Resolve relative refs
git rev-parse HEAD~1 HEAD^2
Terminal window
# Get repository root
git rev-parse --show-toplevel
# Get .git directory path
git rev-parse --git-dir
# Check repository type
git rev-parse --is-bare-repository
# Get current subdirectory
git rev-parse --show-prefix
# Check if in work tree
git rev-parse --is-inside-work-tree
Terminal window
# List all branches
git rev-parse --branches
# List all tags
git rev-parse --tags
# List all remotes
git rev-parse --remotes
# List all references
git rev-parse --all
# Show symbolic refs
git rev-parse --symbolic --branches
Terminal window
# Verify revision exists
git rev-parse --verify HEAD
# Verify and quiet errors
git rev-parse --verify --quiet abc123
# Disambiguate short SHA-1
git rev-parse --disambiguate=abc
# Default revision if none given
git rev-parse --default HEAD
Terminal window
# Resolve paths relative to repository root
git rev-parse --prefix="$(git rev-parse --show-prefix)" -- src/file.txt
# Show path from repository root
git rev-parse --show-prefix
# Combine with other commands
repo_root=$(git rev-parse --show-toplevel)
echo "Repository root: $repo_root"
Terminal window
# Parse command line arguments
git rev-parse --parseopt -- "--all" "--" "$@"
# Extract revisions only
git rev-parse --revs-only HEAD --stat
# Extract non-revisions
git rev-parse --no-revs HEAD --stat
# Parse flags
git rev-parse --flags --all --oneline HEAD
Terminal window
# Show Git environment variables
git rev-parse --local-env-vars
# Get Git directory resolution
git rev-parse --resolve-git-dir .git
# Check Git directory status
git rev-parse --is-inside-git-dir
Terminal window
# Configure abbreviation length
git config core.abbrev 7 # 7-character abbreviations
# Configure reflog references
git config core.logAllRefUpdates true # Enable reflog
# Configure symbolic ref display
git config log.abbrevCommit true # Abbreviate commits
# Configure default behavior
git config core.disambiguate tip # Disambiguation preference
Terminal window
# Always verify before using
if git rev-parse --verify "$ref" >/dev/null 2>&1; then
sha=$(git rev-parse "$ref")
echo "Valid ref: $sha"
else
echo "Invalid ref: $ref"
exit 1
fi
# Handle errors gracefully
sha=$(git rev-parse --verify --quiet "$ref" || echo "")
if [ -z "$sha" ]; then
echo "Could not resolve: $ref"
exit 1
fi
Terminal window
# Cache repository information
repo_root=$(git rev-parse --show-toplevel)
git_dir=$(git rev-parse --git-dir)
# Use short hashes when possible
short_sha=$(git rev-parse --short HEAD)
# Batch operations
refs=$(git rev-parse --all | tr '\n' ' ')
for ref in $refs; do
sha=$(git rev-parse "$ref")
echo "$ref -> $sha"
done
#!/bin/bash
# Build system integration with rev-parse
get_build_info() {
# Get current commit
commit_sha=$(git rev-parse HEAD)
short_sha=$(git rev-parse --short HEAD)
# Get branch name
branch=$(git rev-parse --abbrev-ref HEAD)
# Get repository info
repo_root=$(git rev-parse --show-toplevel)
is_dirty=$(git diff --quiet || echo "dirty")
# Get build timestamp
build_time=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# Export for build system
export GIT_COMMIT="$commit_sha"
export GIT_SHORT_COMMIT="$short_sha"
export GIT_BRANCH="$branch"
export GIT_REPO_ROOT="$repo_root"
export GIT_DIRTY="$is_dirty"
export BUILD_TIME="$build_time"
echo "Build Info:"
echo " Commit: $short_sha"
echo " Branch: $branch"
echo " Dirty: $is_dirty"
echo " Time: $build_time"
}
get_build_info
Terminal window
# CI/CD pipeline commit information
ci_commit_info() {
echo "CI/CD Commit Information"
# Basic commit info
commit_sha=$(git rev-parse HEAD)
short_sha=$(git rev-parse --short HEAD)
branch=$(git rev-parse --abbrev-ref HEAD)
# Repository info
repo_url=$(git config --get remote.origin.url)
repo_name=$(basename "$repo_url" .git)
# Author info
author_name=$(git show -s --format='%an' HEAD)
author_email=$(git show -s --format='%ae' HEAD)
# Commit details
commit_message=$(git show -s --format='%s' HEAD)
commit_date=$(git show -s --format='%ci' HEAD)
# Export for CI
export CI_COMMIT_SHA="$commit_sha"
export CI_COMMIT_SHORT_SHA="$short_sha"
export CI_COMMIT_BRANCH="$branch"
export CI_REPO_NAME="$repo_name"
export CI_COMMIT_AUTHOR="$author_name"
export CI_COMMIT_MESSAGE="$commit_message"
export CI_COMMIT_DATE="$commit_date"
# Output for logging
cat <<EOF
Commit: $short_sha
Branch: $branch
Author: $author_name <$author_email>
Message: $commit_message
Date: $commit_date
Repository: $repo_name
EOF
}
ci_commit_info
Terminal window
# Extract version information from Git
get_version_info() {
# Get latest tag
latest_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
# Get commit count since tag
commits_since_tag=$(git rev-parse --short HEAD)
# Get branch info
branch=$(git rev-parse --abbrev-ref HEAD)
is_main_branch=$(git rev-parse --verify main >/dev/null 2>&1 && echo "true" || echo "false")
# Get build info
build_sha=$(git rev-parse --short HEAD)
build_time=$(date -u +"%Y%m%d%H%M%S")
# Construct version
if [ "$is_main_branch" = "true" ] && [ "$branch" = "main" ]; then
version="$latest_tag"
else
version="$latest_tag-$branch-$build_sha"
fi
# Export version info
export VERSION="$version"
export BUILD_SHA="$build_sha"
export BUILD_TIME="$build_time"
export BRANCH="$branch"
echo "Version: $version"
echo "Build SHA: $build_sha"
echo "Branch: $branch"
echo "Build Time: $build_time"
}
get_version_info
Terminal window
# Debug revision resolution
debug_revision() {
local rev="$1"
echo "Debugging revision: $rev"
# Try to resolve
if git rev-parse "$rev" >/dev/null 2>&1; then
sha=$(git rev-parse "$rev")
echo "Resolved to: $sha"
# Check object type
type=$(git cat-file -t "$sha")
echo "Object type: $type"
# Show object info
case "$type" in
"commit")
git show --no-patch --format="Author: %an <%ae>%nDate: %ad%nSubject: %s" "$sha"
;;
"tree")
echo "Tree object"
;;
"blob")
echo "Blob object"
;;
esac
else
echo "Could not resolve: $rev"
# Check if it's a valid ref
if git show-ref "$rev" >/dev/null 2>&1; then
echo "Valid ref, but resolution failed"
else
echo "Not a valid ref"
fi
fi
}
debug_revision "HEAD~1"
Terminal window
# Debug repository detection
debug_repo_detection() {
echo "Repository Detection Debug"
# Check if in Git repository
if git rev-parse --git-dir >/dev/null 2>&1; then
git_dir=$(git rev-parse --git-dir)
echo "Git directory: $git_dir"
else
echo "Not in a Git repository"
return 1
fi
# Check repository type
if git rev-parse --is-bare-repository >/dev/null 2>&1; then
echo "Bare repository"
else
echo "Working tree repository"
fi
# Check work tree status
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
work_tree=$(git rev-parse --show-toplevel)
echo "Work tree: $work_tree"
current_dir=$(pwd)
prefix=$(git rev-parse --show-prefix)
echo "Current directory: $current_dir"
echo "Prefix from root: $prefix"
else
echo "Not in work tree"
fi
}
debug_repo_detection
Terminal window
# Debug path resolution
debug_path_resolution() {
local path="$1"
echo "Debugging path resolution: $path"
# Check if path exists
if [ -e "$path" ]; then
echo "Path exists on filesystem"
else
echo "Path does not exist on filesystem"
fi
# Check repository root
repo_root=$(git rev-parse --show-toplevel 2>/dev/null)
if [ -n "$repo_root" ]; then
echo "Repository root: $repo_root"
# Get absolute path
abs_path=$(cd "$repo_root" && realpath "$path" 2>/dev/null || echo "N/A")
echo "Absolute path: $abs_path"
# Get relative path from root
rel_path=$(git rev-parse --show-prefix)"$path"
echo "Relative path: $rel_path"
else
echo "Not in a Git repository"
fi
}
debug_path_resolution "src/main.js"
Terminal window
# Debug environment issues
debug_environment() {
echo "Git Environment Debug"
# Show Git environment variables
git rev-parse --local-env-vars
# Check Git configuration
echo "Git config:"
git config --list | grep -E "(user|core|remote)" | head -10
# Check current directory
echo "Current directory: $(pwd)"
echo "Home directory: $HOME"
# Check Git version
git --version
# Check repository status
if git status >/dev/null 2>&1; then
echo "Repository status: OK"
else
echo "Repository status: ERROR"
fi
}
debug_environment
Terminal window
# Optimize rev-parse performance
optimize_revparse_performance() {
echo "Optimizing rev-parse performance"
# Cache frequently used values
export GIT_REPO_ROOT=$(git rev-parse --show-toplevel)
export GIT_COMMIT_SHA=$(git rev-parse HEAD)
export GIT_SHORT_SHA=$(git rev-parse --short HEAD)
# Use short hashes when possible
echo "Using short SHA: $GIT_SHORT_SHA"
# Batch operations
all_refs=$(git rev-parse --all | tr '\n' ' ')
echo "Found $(echo "$all_refs" | wc -w) refs"
# Avoid repeated calls
for ref in $all_refs; do
sha=$(git rev-parse "$ref" 2>/dev/null || echo "ERROR")
echo "$ref -> $sha"
done
}
optimize_revparse_performance
#!/bin/bash
# Pre-commit hook using rev-parse
# Get commit information
commit_sha=$(git rev-parse HEAD)
author_name=$(git show -s --format='%an' HEAD)
author_email=$(git show -s --format='%ae' HEAD)
# Validate commit
if [[ "$author_email" != *@company.com ]]; then
echo "Error: Commits must use company email address"
echo "Current email: $author_email"
exit 1
fi
# Check branch
branch=$(git rev-parse --abbrev-ref HEAD)
if [[ "$branch" = "main" ]]; then
echo "Error: Direct commits to main branch not allowed"
exit 1
fi
# Validate commit message
commit_msg=$(git show -s --format='%s' HEAD)
if [[ ${#commit_msg} -lt 10 ]]; then
echo "Error: Commit message too short (minimum 10 characters)"
exit 1
fi
echo "✓ Pre-commit validation passed"
echo "Commit: $commit_sha"
echo "Author: $author_name <$author_email>"
echo "Branch: $branch"
Terminal window
# Release automation with rev-parse
create_release() {
local version="$1"
local branch="${2:-main}"
echo "Creating release $version from branch $branch"
# Validate branch exists
if ! git rev-parse --verify "$branch" >/dev/null 2>&1; then
echo "Error: Branch $branch does not exist"
exit 1
fi
# Get commit information
release_commit=$(git rev-parse "$branch")
short_commit=$(git rev-parse --short "$branch")
# Check if tag already exists
if git rev-parse --verify "refs/tags/v$version" >/dev/null 2>&1; then
echo "Error: Tag v$version already exists"
exit 1
fi
# Create annotated tag
git tag -a "v$version" -m "Release version $version
Commit: $short_commit
Branch: $branch
Date: $(date -u +"%Y-%m-%dT%H:%M:%SZ")"
# Verify tag
tag_sha=$(git rev-parse "v$version")
if [ "$tag_sha" = "$release_commit" ]; then
echo "✓ Release tag created: v$version"
echo " Commit: $short_commit"
echo " SHA: $tag_sha"
else
echo "Error: Tag creation failed"
exit 1
fi
# Push tag
git push origin "v$version"
echo "✓ Tag pushed to remote"
}
create_release "1.2.3" "release"
Terminal window
# Repository analysis using rev-parse
analyze_repository() {
echo "Repository Analysis Report"
echo "========================="
# Basic repository info
repo_root=$(git rev-parse --show-toplevel)
git_dir=$(git rev-parse --git-dir)
is_bare=$(git rev-parse --is-bare-repository && echo "Yes" || echo "No")
echo "Repository Root: $repo_root"
echo "Git Directory: $git_dir"
echo "Bare Repository: $is_bare"
# Reference counts
branch_count=$(git rev-parse --branches | wc -l)
tag_count=$(git rev-parse --tags | wc -l)
remote_count=$(git rev-parse --remotes | wc -l)
echo "Branches: $branch_count"
echo "Tags: $tag_count"
echo "Remotes: $remote_count"
# Current state
current_branch=$(git rev-parse --abbrev-ref HEAD)
current_commit=$(git rev-parse HEAD)
short_commit=$(git rev-parse --short HEAD)
echo "Current Branch: $current_branch"
echo "Current Commit: $short_commit ($current_commit)"
# Repository health
if git rev-parse --verify HEAD >/dev/null 2>&1; then
echo "HEAD Status: Valid"
else
echo "HEAD Status: Invalid"
fi
# Check for uncommitted changes
if git diff --quiet && git diff --staged --quiet; then
echo "Working Tree: Clean"
else
echo "Working Tree: Modified"
fi
}
analyze_repository
Terminal window
# Automated branch management
manage_branches() {
echo "Branch Management Report"
# Get all branches
all_branches=$(git rev-parse --branches)
# Analyze each branch
for branch in $all_branches; do
echo "Branch: $branch"
# Get branch commit
branch_commit=$(git rev-parse "$branch")
short_commit=$(git rev-parse --short "$branch")
# Check if merged
if git merge-base --is-ancestor "$branch" main 2>/dev/null; then
status="Merged"
else
status="Not merged"
fi
# Get last commit date
last_commit_date=$(git show -s --format='%ci' "$branch")
# Get author
author=$(git show -s --format='%an' "$branch")
echo " Commit: $short_commit"
echo " Status: $status"
echo " Last Commit: $last_commit_date"
echo " Author: $author"
echo ""
done
# Suggest cleanup
echo "Branches that could be deleted:"
for branch in $all_branches; do
if [[ "$branch" != "main" ]] && git merge-base --is-ancestor "$branch" main 2>/dev/null; then
echo " $branch (merged)"
fi
done
}
manage_branches
Terminal window
# Commit message validation using rev-parse
validate_commit_message() {
local commit="$1"
if [ -z "$commit" ]; then
commit="HEAD"
fi
# Get commit message
subject=$(git show -s --format='%s' "$commit")
body=$(git show -s --format='%b' "$commit")
echo "Validating commit: $(git rev-parse --short "$commit")"
echo "Subject: $subject"
issues=0
# Check subject length
if [ ${#subject} -gt 72 ]; then
echo "⚠ Subject too long (${#subject} chars, max 72)"
issues=$((issues + 1))
fi
# Check for period at end
if [[ "$subject" =~ \.$ ]]; then
echo "⚠ Subject ends with period"
issues=$((issues + 1))
fi
# Check imperative mood
if [[ ! "$subject" =~ ^(Add|Fix|Update|Remove|Refactor|Merge|Revert) ]]; then
echo "⚠ Subject should start with imperative verb"
issues=$((issues + 1))
fi
# Check body
if [ -n "$body" ]; then
# Check body line length
while IFS= read -r line; do
if [ ${#line} -gt 72 ]; then
echo "⚠ Body line too long: ${line:0:50}..."
issues=$((issues + 1))
break
fi
done <<< "$body"
fi
if [ $issues -eq 0 ]; then
echo "✓ Commit message validation passed"
return 0
else
echo "✗ Found $issues validation issues"
return 1
fi
}
validate_commit_message "HEAD"

What’s the difference between rev-parse and rev-list?

Section titled “What’s the difference between rev-parse and rev-list?”

rev-parse resolves individual revisions to SHA-1s and provides repository info; rev-list lists multiple commits in ranges and performs set operations.

Use git rev-parse HEAD for full SHA-1, or git rev-parse —short HEAD for abbreviated version.

Yes, git rev-parse main resolves the branch name to its current commit SHA-1.

How do I check if I’m in a Git repository?

Section titled “How do I check if I’m in a Git repository?”

Use git rev-parse —git-dir to get the .git directory path, or check the exit code - success means you’re in a repository.

What’s the difference between —show-toplevel and —show-cdup?

Section titled “What’s the difference between —show-toplevel and —show-cdup?”

—show-toplevel shows the absolute path to repository root; —show-cdup shows relative path from current directory to root (useful for scripts).

Use git rev-parse —abbrev-ref HEAD for the branch name, or git symbolic-ref —short HEAD.

Yes, git rev-parse HEAD~1 resolves to the parent commit, HEAD^2 to the second parent of a merge commit.

How do I list all branches with rev-parse?

Section titled “How do I list all branches with rev-parse?”

Use git rev-parse —branches to list all local branches, —remotes for remote branches, —all for everything.

—disambiguate= helps resolve ambiguous short SHA-1s by showing possible matches when Git can’t uniquely identify a commit.

Yes, git rev-parse —verify returns success if the ref exists and can be resolved, failure otherwise.

How do I get repository information in scripts?

Section titled “How do I get repository information in scripts?”

Use —show-toplevel for repo root, —git-dir for .git path, —is-inside-work-tree to check if in working directory.

—symbolic shows the symbolic names of refs instead of resolving to SHA-1s, useful for seeing what refs point to.

Yes, git rev-parse HEAD@{1} resolves reflog entries to their corresponding commits.

Use git rev-parse —short , which respects the core.abbrev configuration for abbreviation length.

—local-env-vars shows Git-related environment variables that are set locally, useful for debugging Git configuration.

Can rev-parse be used outside a repository?

Section titled “Can rev-parse be used outside a repository?”

Some options like —parseopt work outside repositories, but most require being in a Git repository.

  1. Script Integration: Resolve revisions and get repository information for automation
  2. Build Systems: Extract commit information for version strings and build metadata
  3. CI/CD Pipelines: Get branch names, commit SHAs, and repository state for pipelines
  4. Hook Development: Validate commits and repository state in Git hooks
  5. Repository Analysis: Extract statistics and information about repository structure
  6. Reference Validation: Verify that branches, tags, and commits exist and are valid