Progress:
TIER 3 · MODULE 19· Expert

git update-ref

Move a branch tip without touching HEAD.

🎯 What & why

git update-ref atomically writes a value into a ref file (or packed-refs entry) and, when configured, appends a reflog line. It is how scripts move branch tips without going through checkout, reset, or commit.

🧠 Mental model

A ref is just a file containing a SHA. update-ref does the equivalent of echo <sha> > .git/refs/... but with locking, optional compare-and-swap, reflog updates, and packed-refs awareness. HEAD is never moved as a side effect.

🛠️ Synopsis

git update-ref [-m <reason>] [--create-reflog] [--no-deref]
               <refname> <newvalue> [<oldvalue>]
git update-ref -d <refname> [<oldvalue>]
git update-ref --stdin [-z]   # batch, transactional

🎚️ Switches & options

FlagWhat it does
<refname> <newvalue> [<oldvalue>]Set ref to newvalue; if oldvalue is given, fail unless it currently equals oldvalue (compare-and-swap).
-d, --delete <ref> [<oldvalue>]⚠️ Delete the ref; with oldvalue, only delete if it still points there.
-m <reason>Reflog message to record alongside the update (only used if a reflog exists).
--create-reflogForce-create a reflog for this ref even if core.logAllRefUpdates would not.
--no-derefOperate on the symbolic ref itself, not its target (e.g. rewrite HEAD as a SHA).
--stdin [-z]Read multiple update/delete/create/verify commands and apply them in a single transaction.

📦 Subcommands

update — Set ref to newvalue, optionally verifying oldvalue.
echo 'update refs/heads/main <new> <old>' | git update-ref --stdin
create — Create a ref that must not yet exist.
echo 'create refs/heads/feat <sha>' | git update-ref --stdin
delete — Delete a ref, optionally verifying oldvalue.
echo 'delete refs/heads/old <sha>' | git update-ref --stdin
verify — Assert a ref currently has a given value without changing it.
echo 'verify refs/heads/main <sha>' | git update-ref --stdin

💡 Use cases

🧪 Examples

CAS update of main
git update-ref refs/heads/main <new_sha> <old_sha>
Delete a branch ref by plumbing
git update-ref -d refs/heads/wip
Move a branch with a reflog reason
git update-ref -m 'rebase: onto main' refs/heads/feat <new_sha>
Atomic batch via --stdin
printf 'update refs/heads/a %s\nupdate refs/heads/b %s\n' $A $B | git update-ref --stdin

🎓 Recommendations

🪤 Common pitfalls

🔗 Related modules

📝 Quiz

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