HEAD detached at origin/master

As CommuSoft says, you’re not on master. You’re in “detached HEAD” mode. You get that any time you explicitly check out something that is not a (local) branch name:

$ git checkout origin/master    # detach to "remote branch"

or if there’s a tag v1.7:

$ git checkout v1.7             # detach to tag

and you can even explicitly detach when using a local branch name:

$ git checkout --detach master  # forcibly detach

A “detached HEAD” means you’re not on a branch. Being “on a branch” means you’re not using the detached HEAD mode. Yes, that’s pretty circular; see this question and its answers for more details.

As for the:

error: The following untracked working tree files would be overwritten ...

When you get git checkout to move from one commit to another, it does two main things:

  1. choose whether to be in “detached HEAD” mode, and
  2. rearrange the work tree to match the moved-to commit.

Step 2 is where the problem is occurring. You’re on the commit identified by origin/master, and in that commit, there is no record of the files git is currently complaining about. You’ve asked to switch to the commit identified by master, which is obviously a different commit.1 Git sees that in the commit identified by master, there are some (maybe just one) files with the same names, that are different from the files or directories that are in your work-tree right now.

In order to switch from the current commit to the new one, git checkout must remove the existing files-or-directories and replace them with the ones in the new commit—the one you’re asking to switch to. If those files or directories were tracked in the current commit, git would be happy to remove and replace them as needed, as git can always get them back for you: just switch back to that old commit, and there they are. But they’re not in the current, to-be-switched-away-from, commit. So git tells you: “Hey, if I make this switch you asked for, I can’t guarantee that I’ll be able to restore these files and/or directories.”

It’s now up to you, not git, to figure out what to do with these files and/or directories. Based on the error message, it’s a directory,2 and switching to master will cause that directory to be removed and replaced with something else (possibly a different directory with some file(s) in it, possibly just a file). Do you:

  • want to save it/them?
  • if so, do you want to save it/them in a commit, or just move them out of the way?
  • or do you just want to blow them away?

To save them, either commit them, or move them out of the way (e.g., rename them to a path that’s not part of the work-tree, or to a different untracked name that’s “safer”, whatever that would be).

To simply blow them away, remove them manually or use git checkout -f (force) to make git do it.

Since you’re not on a branch now (are in “detached HEAD” mode), if you want to commit them permanently to the repository, you can use something like the method CommuSoft added while I was writing this up. (You can create the new branch at any time, before or after doing a “git commit”.)

You can also use git stash. Git’s stash is deceptively complex little script: it makes commits that are not on any branch at all, that can later be transplanted to a branch. Using it is quite simple and easy: you just run git stash save and all pending tracked changes are saved and cleaned up, or run git stash save -u and all pending tracked changes and untracked files are saved and cleaned up. They are now all safely squirreled away in the repository, under a commit, even though it’s not a commit-on-a-branch.

There is no single right answer for what to do here.


1Obviously different, because if you were already on the commit you’re asking git to move to, then either the file would be in the commit and hence tracked, or it would be not-in-the-commit and hence you would not be asking git to clobber it.

2This is a little odd. If I make a directory that will be clobbered by my git checkout, and I make it as an empty directory, git just goes ahead and clobbers it. Here the difference between master^ and master is that moving forward from master^ to master creates file mxgroup.py (so stepping back removes it):

$ git checkout -q master^  # file goes away, now let's mkdir...
$ mkdir mxgroup.py; git checkout -q master
$ file mxgroup.py
mxgroup.py: Python script, ASCII text executable

However, if I have a non-empty directory, I get a different error message:

$ git checkout -q master^  # file goes away; mkdir and make file
$ mkdir mxgroup.py; touch mxgroup.py/file; git checkout -q master
error: Updating the following directories would lose untracked files in it:
    mxgroup.py

Aborting

But this is with git version 2.0.2; perhaps older gits are not as clever.

Leave a Comment