Search code examples
gitgit-pushgit-pullgit-checkoutgit-reset

How badly did I hose my git repo?


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!


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