[git] How can I reconcile detached HEAD with master/origin?

I'm new at the branching complexities of Git. I always work on a single branch and commit changes and then periodically push to my remote origin.

Somewhere recently, I did a reset of some files to get them out of commit staging, and later did a rebase -i to get rid of a couple recent local commits. Now I'm in a state I don't quite understand.

In my working area, git log shows exactly what I'd expect-- I'm on the right train with the commits I didn't want gone, and new ones there, etc.

But I just pushed to the remote repository, and what's there is different-- a couple of the commits I'd killed in the rebase got pushed, and the new ones committed locally aren't there.

I think "master/origin" is detached from HEAD, but I'm not 100% clear on what that means, how to visualize it with the command line tools, and how to fix it.

This question is related to git

The answer is


In my case, I ran git status, and I saw that I had a few untracked files in my working directory.

To make the rebase work, I just had to clean them (since I didn't need them).


This worked for me perfectly:

1.git stash to save your local modifications

If you want to discard changes
git clean -df
git checkout -- .
git clean removes all untracked files (warning: while it won't delete ignored files mentioned directly in .gitignore, it may delete ignored files residing in folders) and git checkout clears all unstaged changes.

2.git checkout master to switch to the main branch (Assuming you want to use master)
3.git pull to pull last commit from master branch
4.git status in order to check everything looks great

On branch master
Your branch is up-to-date with 'origin/master'.

If you want to push your current detached HEAD (check git log before), try:

git push origin HEAD:master

to send your detached HEAD into master branch at origin. If your push gets rejected, try git pull origin master first to get the changes from origin. If you don't care about the changes from origin and it's rejected, because you did some intentional rebase and you want to replace origin/master with your currently detached branch - then you may force it (-f). In case you lost some access to previous commits, you can always run git reflog to see the history from all branches.


To get back on a master branch, while keeping the changes, try the following commands:

git rebase HEAD master
git checkout master

See: Git: "Not currently on any branch." Is there an easy way to get back on a branch, while keeping the changes?


If you did some commits on top of master and just want to "backwards merge" master there (i.e. you want master to point to HEAD), the one-liner would be:

git checkout -B master HEAD
  1. That creates a new branch named master, even if it exists already (which is like moving master and that's what we want).
  2. The newly created branch is set to point to HEAD, which is where you are.
  3. The new branch is checked out, so you are on master afterwards.

I found this especially useful in the case of sub-repositories, which also happen to be in a detached state rather often.


When I personally find myself in a situation when it turns out that I made some changes while I am not in master (i.e. HEAD is detached right above the master and there are no commits in between) stashing might help:

git stash # HEAD has same content as master, but we are still not in master
git checkout master  # switch to master, okay because no changes and master
git stash apply  # apply changes we had between HEAD and master in the first place

Just do this:

git checkout master

Or, if you have changes that you want to keep, do this:

git checkout -b temp
git checkout -B master temp

I had the same problem. I stash my changes with git stash and hard reset the branch in local to a previous commit(I thought it caused that) then did a git pull and I am not getting that head detached now. Dont forget git stash apply to have your changes again.


if you have just master branch and wanna back to "develop" or a feature just do this :

git checkout origin/develop

Note: checking out origin/develop.

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

then

git checkout -b develop

It works :)


If you are completely sure HEAD is the good state:

git branch -f master HEAD
git checkout master

You probably can't push to origin, since your master has diverged from origin. If you are sure no one else is using the repo, you can force-push:

git push -f

Most useful if you are on a feature branch no one else is using.


I ran into this issue and when I read in the top voted answer:

HEAD is the symbolic name for the currently checked out commit.

I thought: Ah-ha! If HEAD is the symbolic name for the currenlty checkout commit, I can reconcile it against master by rebasing it against master:

git rebase HEAD master

This command:

  1. checks out master
  2. identifies the parent commits of HEAD back to the point HEAD diverged from master
  3. plays those commits on top of master

The end result is that all commits that were in HEAD but not master are then also in master. master remains checked out.


Regarding the remote:

a couple of the commits I'd killed in the rebase got pushed, and the new ones committed locally aren't there.

The remote history can no longer be fast-forwarded using your local history. You'll need to force-push (git push -f) to overwrite the remote history. If you have any collaborators, it usually makes sense to coordinate this with them so everyone is on the same page.

After you push master to remote origin, your remote tracking branch origin/master will be updated to point to the same commit as master.


I had the same problem and I have resolved it by going through the following steps.

If you need to keep your changes

  1. First you need to run git checkout master command to put you back to the master branch.
  2. If you need to keep your changes just run git checkout -b changes and git checkout -B master changes

If you don't need your changes

  1. To removes all untracked files from your branch run git clean -df.

  2. Then you need to clear all unstaged changes within your repository. In order to do that you have to run git checkout --

  3. Finally you have to put your branch back to the master branch by using git checkout master command.


The following worked for me (using only branch master):

git push origin HEAD:master
git checkout master        
git pull

The first one pushes the detached HEAD to remote origin.

The second one moves to branch master.

The third one recovers the HEAD that becomes attached to branch master.

Problems might arise at the first command if the push gets rejected. But this would no longer be a problem of detached head, but is about the fact that the detached HEAD is not aware of some remote changes.


If you are using EGit in Eclipse: assume your master is your main development branch

  • commit you changes to a branch, normally a new one
  • then pull from the remote
  • then right click the project node, choose team then choose show history
  • then right click the master, choose check out
  • if Eclipse tells you, there are two masters one local one remote, choose the remote

After this you should be able to reattach to the origin-master.


I got into a really silly state, I doubt anyone else will find this useful.... but just in case

git ls-remote origin
0d2ab882d0dd5a6db93d7ed77a5a0d7b258a5e1b        HEAD
6f96ad0f97ee832ee16007d865aac9af847c1ef6        refs/heads/HEAD
0d2ab882d0dd5a6db93d7ed77a5a0d7b258a5e1b        refs/heads/master

which I eventually fixed with

git push origin :HEAD

Instead of doing git checkout origin/master

just do git checkout master

then git branch will confirm your branch.


In simple words, the detached HEAD state means you are not checked out to HEAD (or tip) of any branch.

Understand With an Example

A branch in most of the cases is sequence of multiple commits like:

Commit 1: master-->branch_HEAD(123be6a76168aca712aea16076e971c23835f8ca)

Commit 2: master-->123be6a76168aca712aea16076e971c23835f8ca-->branch_HEAD(100644a76168aca712aea16076e971c23835f8ca)

As you can see above in case of sequence of commits, your branch points to your latest commit. So in that case if you checkout to commit 123be6a76168aca712aea16076e971c23835f8ca then you would be in detached head state since HEAD of your branch points to 100644a76168aca712aea16076e971c23835f8ca and technically you are checked out at HEAD of no branch. Hence, you are in the detached HEAD state.

Theoretical Explanation

In this Blog it's clearly stating a Git repository is a tree-of-commits, with each commit pointing to its ancestor with each commit pointer is updated and these pointers to each branch are stored in the .git/refs sub-directories. Tags are stored in .git/refs/tags and branches are stored in .git/refs/heads. If you look at any of the files, you'll find each tag corresponds to a single file, with a 40-character commit hash and as explained above by @Chris Johnsen and @Yaroslav Nikitenko, you can check out these references.


Get your detached commit onto its own branch

Simply run git checkout -b mynewbranch.

Then run git log, and you'll see that commit is now HEAD on this new branch.


All you have to do is 'git checkout [branch-name]' where [branch-name] is the name of the original branch from which you got into a detached head state. The (detached from asdfasdf) will disappear.

So for example, in branch 'dev' you checkout the commit asdfasd14314 ->

'git checkout asdfasd14314'

you are now in a detached head state

'git branch' will list something like ->

* (detached from asdfasdf)
  dev
  prod
  stage

but to get out of the detached head state and back to dev ->

'git checkout dev'

and then 'git branch' will list ->

* dev
  prod
  stage

but that is of course if you do not intend on keeping any changes from the detached head state but I find myself doing this a lot not intending to make any changes but just to look at a previous commit


For me it was as easy as deleting the local branch again, since I didn't have any local commits that I wanted to push:

So I did:

git branch -d branchname

And then checking the branch out again:

git checkout branchname

I just ran into this issue today and am pretty sure I solved it by doing:

git branch temp
git checkout master
git merge temp

I was on my work computer when I figured out how to do this, and now I'm running into the same problem on my personal computer. So will have to wait till Monday when I'm back at the work computer to see exactly how I did it.


Look here for basic explanation of detached head:

http://git-scm.com/docs/git-checkout

Command line to visualize it:

git branch

or

git branch -a

you will get output like below:

* (no branch)
master
branch1

The * (no branch) shows you are in detached head.

You could have come to this state by doing a git checkout somecommit etc. and it would have warned you with the following:

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.

If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example:

git checkout -b new_branch_name

Now, to get them onto master:

Do a git reflog or even just git log and note your commits. Now git checkout master and git merge the commits.

git merge HEAD@{1}

Edit:

To add, use git rebase -i not only for deleting / killing commits that you don't need, but also for editing them. Just mention "edit" in the commit list and you will be able to amend your commit and then issue a git rebase --continue to go ahead. This would have ensured that you never came in to a detached HEAD.


git checkout checksum  # You could use this to peek previous checkpoints
git status # You will see HEAD detached at checksum
git checkout master # This moves HEAD to master branch

I found this question when searching for You are in 'detached HEAD' state.

After analyzing what I had done to get here, as compared with what I had done in the past, I discovered that I had made a mistake.

My normal flow is:

git checkout master
git fetch
git checkout my-cool-branch
git pull

This time I did:

git checkout master
git fetch
git checkout origin/my-cool-branch
# You are in 'detached HEAD' state.

The problem is that I accidentally did:

git checkout origin/my-cool-branch

Rather than:

git checkout my-cool-branch

The fix (in my situation) was simply to run the above command and then continue the flow:

git checkout my-cool-branch
git pull

As pointed by Chris, I had following situation

git symbolic-ref HEAD fails with fatal: ref HEAD is not a symbolic ref

However git rev-parse refs/heads/master was pointing to a good commit from where I could recover (In my case last commit and you can see that commit by using git show [SHA]

I did a lot messy things after that, but what seems to have fixed is just,

git symbolic-ref HEAD refs/heads/master

And head is re attached!


I had this problem today, where I had updated a submodule, but wasn't on any branch. I had already committed, so stashing, checkout, unstashing wouldn't work. I ended up cherry-picking the detached head's commit. So immediately after I committed (when the push failed), I did:

git checkout master
git cherry-pick 99fe23ab

My thinking went: I'm on a detached head, but I want to be on master. Assuming my detached state is not very different from master, if I could apply my commit to master, I'd be set. This is exactly what cherry-pick does.