I have a local Git repository I\'ve been developing under for a few days: it has eighteen commits so far. Tonight, I created a private Github repository I was hoping to push
So, it turns out that both: the commit hash in .git/refs/heads/master was in correct and the information in .git/logs/refs/heads/master was incomplete; in that I mean it only went up to and included the commit hash specified in .git/refs/heads/master.
Once I fixed these files (by hand), and pushed back to Github, everything was gravy again. I still have no idea what happened to get things in this state, but I'm glad I've at least figured out the fix.
In case anyone is wondering: to fix .git/refs/heads/master, I just replaced the content of that file with the latest commit hash (HEAD), and to fix .git/logs/refs/heads/master, I simply copied the contents of .git/logs/HEAD into .git/logs/refs/heads/master. Easy peasy... NOT.
From Git 1.7.3 onwards, you can do this with one simple command:
git checkout -B master
The -b
switch means “create branch here before checking it out” and -B
is the unconditional version of that, “even if the branch already exists – in that case, move it here before checking it out”.
A very simple approach for fixing this sort of problem is to just delete the master
branch and recreate it. After all, branches in git are merely names for commits and the master
branch is nothing special.
So assuming that the current commit is the one you want master
to be, you simply do
git branch -D master
to delete the existing master
branch, then do
git checkout -b master
to a) create a new branch called master
that points to the current commit and b) update HEAD
to point to the master
branch. After that, HEAD
will be attached to master
and therefore master
will move forward whenever you commit.
I don't have the reputation to comment directly on CesarB's earlier answer, but gitk --all
doesn't work in this case because it only lists out known branches.
gitk HEAD
shows this problem, but it's not entirely clear. The smoking gun is that master
shows up down the commit tree rather than at the most recent commit.
Check if you are pushing the correct branches, and that the branches actually have what you think they have. In particular, check if you do not have a detached HEAD, which can be quite confusing if not done on purpose.
The easiest way to check is to use gitk --all
, which shows graphically all the branches, the HEAD, and more.
I took a look at the repository in question and here's what was going on:
git checkout [commit id]
. This pointed HEAD at a loose commit rather than a recognized branch. I believe this is the "dangling HEAD" problem that CesarB is referring to.This diagram should make it more clear:
-- D -- E -- F
/ ^
A -- B -- C - |
^ ^ HEAD
| |
remote master
When he tried to push his changes, only A
through C
were pushed and remote
moved up to C
. He couldn't get commits D
through F
to push because they aren't referenced by a known branch.
Here's what you see when you're in this state:
$ git branch
* (no branch)
master
The solution is to move master
up to F
in the dangling chain of commits. Here's how I did it.
Create a legitimate branch for the current state:
git checkout -b tmp
tmp
branch is now pointing at commit F
in the diagram aboveFast-forward master
to tmp
git checkout master
git merge tmp
master
is now pointing at commit F
. Throw away your temporary branch
git branch -d tmp
You can happily push to the remote repository and it should send all of your changes.
I suppose the first thing I would do would be to run git fsck
on your local repository to make sure that it is all in good order.
I've never seen this problem before, and I can't think of what might be wrong.