Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git: HEAD has disappeared, want to merge it into master [closed]

Tags:

git

reflog vs GITK http://siteroller.net/archive/images/Forums/headless%20GIT.png

The top image is the output of: git reflog.
The bottom is what GITK in GIT GUI (msysgit) shows me when I look at all branch history.

The last few commits do not show on GIT GUI.

  • Why do they not show on GITK (at least as a branch or something)?
  • How do I merge them into master?
  • I gather this happened when I checked out tag 0.42. Why is that not the same as master? (I had tagged the master in its latest state)
  • When I click push, why does the remote repo claim to be up to date.. shouldn't it try to update these commits into whatever branch they are in?

The first of the questions is important - I would like to begin to understand what GIT is thinking. It's more oracle than logic at this point.

If it makes a difference to see the earlier history, the project is a [pretty powerful] JS color picker that can be viewed here in its entirety.

like image 892
SamGoody Avatar asked Mar 25 '10 20:03

SamGoody


3 Answers

why to update these commits into whatever branch they are in?

That's just it: you are not on any branch but currently working on a detached head:

starting from version 1.5.0, the above command detaches your HEAD from the current branch and directly points at the commit named by the tag.

You might see it if you do a gitk --all

One way to fix it (if you have committed everything)

$ git log -1
# note the SHA-1 of latest commit
$ git checkout master
# reset your branch head to your previously detached commit
$ git reset --hard <commit-id>

Another way would be to merge your work into the current master HEAD which happens to be at the tag:

 $ git checkout -m 0.42

but that looses the history of your commits made on a detached HEAD.


I gather this happened when I checked out tag 0.42. Why is that not the same as master? (I had tagged the master in its latest state)

No it is not the same than master. As Jefromi points out in the comments, branch can move (or be renamed, or deleted, or...)
master was referring to the same commit than the '0.42' tag, but that won't be always the case.
With a checkout of a tag, you do not checkout a branch, hence the 'detached HEAD' state.


Note: as mentioned in this SO answer, the @{1} notation you see is $(git symbolic-ref HEAD)@{1}, i.e. it is uses reflog for current (here detached) branch, not HEAD reflog.

like image 153
VonC Avatar answered Nov 08 '22 06:11

VonC


In Git commits form a directed acyclic graph where each commit points to one or more parent commits. In addition to the commit objects you also have ref (i.e. reference) objects: branches and tags. They point to various commits in the commit graph. Your problem is that you weren't on a branch when you made the commits and no branch (or tag) points to them. At any time you can use commands

git status

and

git branch

to check whether you are on a branch or not.

Why do they not show on GITK (at least as a branch or something)?

As far as I know Gitk looks for the commit objects starting from the refs. If no ref points to your commits (or the directed acyclic graph of commits that leads to them) they are effectively invisible.

How do I merge them into master?

Fortunately the reflog facility keeps track of operations like checkouts and commits (among other things). In your reflog listing you can see the entry for your last commit:

1b8c11d HEAD@{1} commit: Shortened toRgb() function

You should be able to merge the commits to your master branch by using the SHA1 ID you see in the reflog:

git checkout master
git merge 1b8c11d

I gather this happened when I checked out tag 0.42. Why is that not the same as master? (I had tagged the master in its latest state)

The main difference between branches and tags is that a tag always points to the same commit but a branch moves forward. For example, if you are on branch "master" and make a new commit, the "master" branch moves forward and starts pointing to the new commit you just created. When you checkout commits, tags or branches Git takes your commands quite literally and checks out exactly what you asked for.

When I click push, why does the remote repo claim to be up to date.. shouldn't it try to update these commits into whatever branch they are in?

Your commits aren't on any branch. You first need to merge them to a branch (e.g. to master) as shown above. After this the push should work normally.

like image 22
kaitanie Avatar answered Nov 08 '22 06:11

kaitanie


The easiest way to resurrect your commits is to point some branch head to them. You know the SHAs, so it's easy:

git branch resurrected_junk 1b8c11d

(this is a SHA read from your screenshot), could be also

git branch resurrected_junk HEAD@1

This will point a branch to the most recent of your lost commits - the earlier ones are probably parents of the most recent one, so they will be on this new branch; if they aren't (that means there are two "shadow branches" of lost commits), you would have to review all the commits and reiterate the procedure for the commits that are missing.

In your case, I guess you'll get a history like this:

Master --> Optimize toRGB --> ... ---> shortened toRGB = resurrected_junk

Then, refresh your gitk view and the commits should show up. (I'm using qgit, so I'm just guessing)

After that, you should be able to merge/push/whatever yow want them (as you like).

like image 45
jpalecek Avatar answered Nov 08 '22 06:11

jpalecek