I've just checked out an old project to fix a bug. git reports:
HEAD detached at origin/master
git status
reports I have an untracked file:
<project name>.xcworkspace/xcshareddata/
I'd like to get on and fix the bug but I'm not sure quite what's going on. If I try git checkout master
I get:
error: The following untracked working tree files would be overwritten by checkout: <project name>.xcworkspace/xcshareddata/
Can I just delete this file? Am I on the master
branch? If not, how do I get to it?
You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. Now, to get them onto master: Do a git reflog or even just git log and note your commits.
What does detached HEAD mean? In Git, HEAD refers to the currently checked-out branch's latest commit. However, in a detached HEAD state, the HEAD does not point to any branch, but a specific commit or the remote repository.
If you want to keep changes made with a detached HEAD, just create a new branch and switch to it. You can create it right after arriving at a detached HEAD or after creating one or more commits. The result is the same. The only restriction is that you should do it before returning to your normal branch.
You must understand that any of your branches will not be affected if you ever get into a detached state . Now, the best way to reattach the HEAD is to create a new branch. We can do it as simple as git checkout -b <branch-name> . This will commit the changes from your temporary branch into the branch you need them.
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:
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:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With