Git Basics: Build an Explicit Local Branch Inventory
A script can list branches with a stable field selection instead of parsing the human-oriented branch display. for-each-ref also lets you restrict the namespace being inspected.
Prepare a scratch directory
Tested on Linux with Git 2.52.0 and GNU Bash 5.2.37. You need Bash, a text editor, the named runtime, and standard mktemp, rm, and rmdir utilities. The examples use only controlled local data; generated fixture directories are cleaned automatically.
Keep the same terminal open. Stop if setup fails, before saving the source:
start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 1Run the example
Save this as demonstrate-for-each-ref.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
export GIT_AUTHOR_NAME='Example Author'
export GIT_AUTHOR_EMAIL='author@example.invalid'
export GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"
export GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"
export GIT_AUTHOR_DATE='2026-10-28T00:00:00+00:00'
export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
git init -q -b main "$fixture_dir/repo"
cd -- "$fixture_dir/repo"
git config commit.gpgsign false
git config core.hooksPath /dev/null
git commit -qm 'Base snapshot' --allow-empty
git branch topic
git tag v1
git switch -q topic
git commit -qm 'Topic snapshot' --allow-empty
printf 'Branch inventory:\n'
git for-each-ref --sort=refname --format='%(refname:short)|%(objecttype)|%(subject)' refs/heads/
printf 'Tag inventory:\n'
git for-each-ref --sort=refname --format='%(refname:short)' refs/tags/
test "$(git for-each-ref --format='%(refname)' refs/heads/ | wc -l)" -eq 2Run it:
bash demonstrate-for-each-ref.shObserved output:
Branch inventory:
main|commit|Base snapshot
topic|commit|Topic snapshot
Tag inventory:
v1Read the result
refs/heads selects local branches, while refs/tags selects tags. Sorting by full ref name gives a repeatable order. The branch records expose the short ref name, target object type, and commit subject without including transient terminal decorations.
Apply it carefully
The vertical bar is only a convenient display delimiter for these controlled subjects. Arbitrary commit text can contain delimiters; choose an appropriate machine-safe format before parsing untrusted metadata. This local inventory does not contact a remote or refresh tracking refs. Run this script from an ordinary shell with no repository-selection variables such as GIT_DIR or GIT_WORK_TREE set. All commits and cleanup stay inside the newly created temporary fixture.
The official reference describes the behavior and options. These checks cover the fixture above rather than every input or platform.
Clean up
Remove the saved source, return to the starting directory, then remove the empty practice directory:
rm -- demonstrate-for-each-ref.sh
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dirIf the directory is not empty, inspect its remaining contents rather than deleting unknown files.
Acknowledgements
This post was created with assistance from AI.