Question

My project has a bare repo setup on the server. I'm currently on branch 0.9/develop. I merged 0.9/develop with a branch that another developer was working on. It turns out that it would be way more work to fix his code than to obliterate his changes entirely. Unfortunately, I already ran a git push origin 0.9/develop after having committed the merge AND I pulled those changes to my development AND staging servers (yes, I'm stupid).

I've been going through a bunch of somewhat similar questions on SO, but none of them quite seem to cover my exact case. This one was particularly useful: How to revert Git repository to a previous commit?

Using info from that question, I was able to successfully obliterate the last commit off of the project. Specifically, I did a git reset --hard f6c84a0, which successfully reset my local repository to the commit right before I merged the other developer's n00bery into my poetry.

Okay, great. Now I just need to get the bare repo fixed up. So I tried git push --force origin 0.9/develop. Unfortunately I lost the specific message that the server sent back, but it was something along the lines of "success", and it showed that the remote repo had been updated to commit f6c84a0.

When I tried to ssh into the server and then go to my staging environment and run a git pull, the response was:

From /home/ben/web/example
 + 77d54e4...f6c84a0 0.9/develop -> origin/0.9/develop  (forced update)
Already up-to-date.

However, when I ran a git log from the staging server, all of the commits from the merge are still on the 0.9/develop branch. I tried a couple of things, like git pull --force, but I couldn't get the bad commits to go away.

Okay, fine. There's more than one way to skin a cat. I wiped the staging server clean and did a fresh git clone --recursive --no-hardlinks example.git stage.example.com and ran the necessary setup script that does a few little server maintenance things.

Now I can't get back to my 0.9/develop branch. In the past, I have simply run git checkout 0.9/develop, but if I try that now, I get this:

Branch 0.9/develop set up to track remote branch 0.9/develop from origin.
Switched to a new branch '0.9/develop'

Wait...what? 0.9/develop is not a new branch. Working with info from this question: How to clone all remote branches in Git? I did a git branch -a and got the following:

* 0.9/develop
  master
  remotes/origin/0.8/develop
  remotes/origin/0.8/master
  remotes/origin/0.9/develop
  remotes/origin/HEAD -> origin/master
  remotes/origin/category-address
  remotes/origin/jaminimaj
  remotes/origin/master
  remotes/origin/permissions
  remotes/origin/ticket-duration
  remotes/origin/timzone-support

I then tried git checkout origin/0.9/develop, but I got the following message:

Note: checking out 'origin/0.9/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.

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

HEAD is now at f6c84a0... bugfix: revert email helper

Well, the good news is the staging server now has the proper code base, but I'm in a detached HEAD state. I realize that I'm probably missing something very minor here, but it certainly is messing with my Friday evening. How can I get my staging server HEAD pointing back to the HEAD of 0.9/develop? Also, I want to do the same thing on my development environment, but I'd rather do it in the proper git fashion than erasing the whole server and starting over again. Can I do that, or will I just have to brute-force it by rebuilding the server from the repo? Thanks for the help everybody!

Was it helpful?

Solution

The message

Branch 0.9/develop set up to track remote branch 0.9/develop from origin.
Switched to a new branch '0.9/develop'

means the following:

  • git created a new branch pointer named 0.9/develop that points to the current head of origin/0.9/develop
  • This branch pointer has auto-generated configuration settings to track the remote branch so that git pull and git push work as expected.

So it does what it's supposed to do. It's just a bit counter-intuitive, basically to work with a branch you need a local branch in the repository you cloned. This is merged with the remote branch whenever you run git pull.

By the way, git pull in the tracking branch is equivalent to

git fetch
git merge remotes/origin/0.9/develop

OTHER TIPS

It sounds like you need to check out the branch in the bare repo and use git reset to reset it back to where you want it. Alternatively, you can git reset the local branch in your local repo and git push -f it. In the staging repo, you have to do a git reset just like you do in your normal working repo.

Possibly your root problem is answered here

After manipulation like yours client must reset back a few commits and pull again, as their repo is ahead the forced push.

If you happen to be on detached hear, don't worry just checkout a local branch. It happens easily if you use checkout on a direct hash, a tag or a remote branch, or just got in the middle of some operation. It just means you're on no branch currently.

You got it by

git checkout origin/0.9/develop

It's unclear whether you lost your local branches or not. use git branch to see whether you have 0.9/develop or not, and if so, checkout that. If not, start git gui and use create branch menu to create it from the tracking branch.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top