Progress:
TIER 3 · MODULE 27· Expert

git for-each-ref

The duct tape of any ref-related script you'll ever write.

🎯 What & why

Iterates refs and prints fields you choose with a format string. It is the duct tape of every ref-handling script you will ever write - and it replaces the fragile for ref in $(git branch) pattern.

🧠 Mental model

A SELECT statement over refs/: pick atoms with %(...), filter by reachability or pointee, sort by any atom, cap with --count. Quoted, NUL-safe, and aware of peeled tags - everything ad-hoc shell loops get wrong.

🛠️ Synopsis

git for-each-ref [--count=<count>] [--shell|--perl|--python|--tcl]
                 [(--sort=<key>)...] [--format=<format>]
                 [--include-root-refs] [ --stdin | <pattern>... ]
                 [--points-at=<object>]
                 [--merged[=<object>]] [--no-merged[=<object>]]
                 [--contains[=<object>]] [--no-contains[=<object>]]
                 [--exclude=<pattern>...]

🎚️ Switches & options

FlagWhat it does
--format=<fmt>Format string with atoms like %(refname), %(objectname), %(committerdate:iso), %(authoremail), %(upstream:short).
--sort=<key>Sort by an atom; prefix with - to reverse; repeat for multi-key sort (e.g. --sort=-committerdate).
--count=<n>Stop after the first n matches - cheap top-N once paired with --sort.
--contains <commit>Only refs whose tip has <commit> as ancestor; --no-contains for the inverse.
--merged[=<commit>]Only refs reachable from <commit> (default HEAD); --no-merged for unmerged ones.
--points-at <object>Only refs that point directly at <object> (peeled, so it works for tags).
<pattern>...Glob patterns like refs/heads/ or refs/tags/v; without any, all refs are listed.

💡 Use cases

🧪 Examples

Branches sorted by most recent commit
git for-each-ref --sort=-committerdate --format='%(refname:short) %(committerdate:relative) %(authoremail)' refs/heads/
Top 10 stale branches (oldest first)
git for-each-ref --sort=committerdate --count=10 --format='%(refname:short) %(committerdate:short)' refs/heads/
Tags that contain a given commit
git for-each-ref --contains <sha> --format='%(refname:short)' refs/tags/
Branches not yet merged into main
git for-each-ref --no-merged main --format='%(refname:short)' refs/heads/

🎓 Recommendations

🪤 Common pitfalls

🔗 Related modules

📝 Quiz

Hit each option, then Check answers. Score is recorded; Next is always open.