keyboard-shortcut
d

ORIG_HEAD 🪄

2min read

an image

What is ORIG_HEAD

ORIG_HEAD is a value preserved in git that stores the previous state of HEAD before you do anything dangerous 🔥. You can view it with git show ORIG_HEAD.

What are these "dangerous" commands?

ORIG_HEAD is updated every time you start a dangerous command. These include:

  • merge
  • rebase
  • reset

These are considered dangerous because they remove commits from your history. Don't worry, those commits still exist in your reflog (which is how checking out ORIG_HEAD is able to still find those commits), but ORIG_HEAD can help prevent your from trawling through the reflog (never a fun task).

How is this useful?

Undoing a bad "reset"

A great example is when you use the incorrect git reset strategy:

  • soft - remove commits, but preserve all current file changes and leave them staged
  • mixed - remove commits, but preseve all file changes, but don't stage them
  • hard - remove commits and delete all file changes

If you ran hard instead of soft/mixed you might find it tricky rummaging through the reflog to find the correct changes. Instead you can retrieve the commit hash easily with git show -s ORIG_HEAD --format="%H". You can then reset back to the point you started at: git reset --hard $(git show -s ORIG_HEAD --format="%H").

"Borrowing" messages when rebasing commits

Sometimes when rebasing I will split some changes out of a commit and put it in a new commit (because it's not part of that logical set of changes). To do this, I'll:

  • start an interactive rebase with git rebase -i main (or similar)
  • mark my commit with an e to "edit" it
  • reset the commit in question, preserving file changes using the default mixed strategy: git reset HEAD~1. Note at this point the ORIG_HEAD will be updated with the hash of the commit we've just undone 🤔
  • I can stage/commit the changes I want in the "first" commit 👍
  • More often than not, I'll then just stage everything else and I just want to re-write the original commit message we had previously. I used to steal the previous commit message from github (or similar), but now I just use the information in ORIG_HEAD!
  • git commit -e -m "$(git show -s ORIG_HEAD --format="%s%n%n%b")". The -e flag allows me to still edit the message if I need to. The "format" is just a handy way of only extracting the information I want (the title and body of the commit with some line separators to make it legible).

Notes

  • It's important to remember that ORIG_HEAD is ephemeral. It gets overwritten each time a new "qualifying" operation is performed (like another merge, rebase, or reset). It may be helpful getting you out of a sticky situation, but don't rely too heavily!
  • Not all operations update ORIG_HEAD. Simple commits or checkouts do not update ORIG_HEAD.