Git Tips: What is a headless state?

Matt Reimer
North Arrow Research
3 min readDec 23, 2016

Every now and then you’re going to get a weird git error called a “headless state”. This can be perplexing if all you want to do is push your changes and go home. It’s important to understand what’s going on here though.

Getting out of a headless state is easy:

git init --ichabod-crane
git find horseman
git destroy horseman
git retrieve HEAD

Kidding. Sorry. Bad git humour. Let’s start with a quick digression about HEAD

What is HEAD anyway?

Think of HEAD like a special branch that you can never push. Its only job is to point to where you are on your current repo. It’s kind of like a big red dot on a map telling you “YOU ARE HERE!”

When you’re working on a local repo, HEAD is a really useful concept to get around finding the hash codes for for commits.

* 830f9c2 (HEAD, gh/dev, dev) changing the math interface
* 835e55b minor fix to slope
* 03ca206 fixing a compare problem and some sloppy merge artifacts
| * b2004c4 (konradPNG) I've done all I can for now.
| * ee8a693 adding in the Konrad's Raster2PNG stuff
|/
* c028ec8 fixing areathresh rewrite
* 1942246 fixing slope interface
* da47d55 moving the main queue to RasterArray
* d317aea starting to prototype a new non-recursive areathreshold

You can see in this tree structure that HEAD is currently pointing at the devbranch.

Now I could write git diff 830f9c2..835e55b~1 to get all the changes between where I am now and the last commit but here’s the thing: I’m REALLY lazy and a sloppy typist so A) I don’t want to look up those hashes every time and B) I’m probably going to get them wrong. Enter the concept of HEAD

git diff HEAD..HEAD~1

The tilde ~1 notation means “minus 1”. So diff HEAD..HEAD~1 means the difference between where I am now and the last commit.

That was a quick digression. Back to the problem at hand:

Oh no! Git lost it’s head?!?

First of all don’t worry. This is a “normal” state for git and you haven’t broken anything. It happens a lot when you have submodules.

If you haven’t made a commit.

All you have to do is check out a branch or tag and git’s HEAD will re-attach.

  1. If you’re on a submodule and you don’t need to make a commit don’t sweat it. Git is just fine chilling out in a headless state.
  2. If you’re on a submodule and do need to make a commit just checkout the submodule’s branch (probably the branch you’re on) and get to work.

If you have made commit(s)

First of all don’t beat yourself up. It happens. Here’s what you want to do:

  1. Make a new temporary branch: git checkout -b temp
  2. Now you can rebase this new branch on top of the integration branch: git rebase dev
  3. Checkout dev and merge with temp. Now that you’ve rebased tempshould be stacked directly on top of dev so the merge should happen cleanly in a fast-forward way and without a commit.
  4. Last step is to delete your temporary branch: git branch -d temp

If that last step complains don’t force it. It means you haven’t done something right and temp isn’t merged properly.

All done.

See? Nothing to worry about. As always, git comes through for us and makes life easy. If fixing headless states were that easy in real life the French revolution would be a very different history lesson.

--

--

Matt Reimer
North Arrow Research

Maker and doer of things, software developer, fiddle enthusiast.