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:
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
.