8

I had a bunch of separate branches, and I wanted to merge them, as each of them was an update to a different part of the program.

I guess I was supposed to merge them but instead I ran a git commit -a after cheking out each branch.

Then I realized the whole program went back in time, so I ran a git reset --soft HEAD (I read in an article somewhere that this should help), but that didn't do anything.

I also got this message from git about manually removing some ./git/index.lock so I moved it to ./git/backup_of_index.lock, but that didn't seem to do anything, either.

How do I fix my repository and merge all the branches?

  • 3
    Revert to an old backup always works for me – Tom Gullen Aug 21 '10 at 23:43
  • 8
    First, make a complete backup of your working tree and `.git` folder now and put it somewhere safe, preferably read-only. From what you've said it sounds very unlikely that you have lost work (no `reset --hard`, and it sounds like you were messing with things committed onto branches). Once you've done that go and find a git expert on an interactive channel somewhere who can talk you through how to search and restore your previous state. stackoverflow is almost certainly not the forum for this because you need interactive help, not just a Q&A. – CB Bailey Aug 21 '10 at 23:52
  • Thanks everyone, I will use all the suggestion and figure something out, I can't really pick an answer yet. –  Aug 25 '10 at 13:51
  • Git is great, and you really should know how to use it from the command line. However, when it comes to branching/merges/pretty much anything aside from simple commits and pushes, I am much more comfortable using a good GUI. If you are on windows, I would strongly suggest "Git Extensions". Oddly enough, there isnt a good all in one solution on linux, but plain old git-gui and giggle get the job done for me. – jdc0589 Aug 21 '10 at 23:48

4 Answers4

14

The most important git command in this situation is git reflog. The reflog tracks all changes to each particular branch head, and the git reflog command lists all of the changes to the branch head going back in time.

If you can identify a "good" commit id using the reflog (and it will be there, somewhere), then you are way ahead of where you are now. If a good commit id is say, abc123, then the command:

git checkout -b rescue abc123

creates a new branch called rescue at the commit id abc123.

When I was learning git, I had a similar sort of "where the heck am I and how did I get here?" moment. I learned about the reflog on a different Stack Overflow question, and it's been the most valuable thing to know about Git.

Community
  • 1
  • 1
Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • I second this comment as the one you should pay attention to Jonathan. Run `git reflog` (or `git log -g` to get the same information with some more data), find the last commit that was good and checkout a branch at that point. – Scott Chacon Aug 22 '10 at 00:19
  • Also, there is a bit of documentation on a situation like this here: http://progit.org/book/ch9-7.html#data_recovery – Scott Chacon Aug 22 '10 at 00:21
  • I was coming in here to say "reflog!" just from the title of the question alone. – masonk Aug 22 '10 at 13:01
  • unfortunately I already listen to someone else and reset the head so when I run git reflog, the head{0} is already after the mess –  Aug 25 '10 at 13:18
  • 2
    @jsd911: That's fine. Resetting the head doesn't delete the reflog or anything. The reflog keeps track of each change to the head of your branch. It remembers them all, so whenever the branch changes, the *previous* value is stored at the top of the reflog. Looking at the reflog is a walk back in time that contains every change to your branch. So if your branch at some point in the past contained a "correct" commit id, then it will be in the reflog. – Greg Hewgill Aug 25 '10 at 19:31
4

Unless you have hacked at the data in the .git directory, it is unlikely that you've lost anything. You may have a terrible mess to clean up, and it may take a lot of working out what you did and where it is, but you probably haven't lost anything.

That's the good news.

The bad news is that it is going to be fiendishly difficult for anyone to help you much.

You are likely to need to identify all the branches, and trace backwards the commits on each. You'll need to decide whether all those 'git commit -a' operations were a good idea. It sounds unlikely - so you may need to do your merges properly, working from the next to last commit on each branch.

You also need to decide what you were really trying to do.

It sounds like you wanted to merge some number of branches - call them BranchA, BranchB, and BranchC - onto the main branch, master. But it is not clear that is what you tried.

Given that things are something of a mess, I recommend creating another branch which we can call 'Fixup'. Create this from the head of the master branch. Then, merge the appropriate version of each of BranchA, BranchB and BranchC into the Fixup branch. At each stage, check that the code actually works correctly - passing its test suite, etc. Check in each merge separately on the Fixup branch.

When you are satisfied that the Fixup branch is correct, switch back to the master branch and merge the Fixup branch to master.


Charles Bailey makes the very sensible suggestion (in a comment to the question): before you do anything else, make a backup copy of what you've got, exactly as it currently is. Only then proceed with any cleanup operations. And his suggestion to get interactive help is also sensible.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
1

Mistakes:

  1. "I started playing with git on my new project"
  2. "I just wanted to merge them as each of them were an update to different parts of the program"

You should not be playing with unfamiliar territory when your code means something. If you wish to do this, at least have a fall back plan.

Disaster recovery seems is only important to those that need it the most but at that point it is too late.

I am all for experimentation but I hate seeing this type of situation, I feel bad for the developer as I know his shoes all too well however after you learn this mistake once you will never forget it.

Before you decide to play, take your code and toss it somewhere else so when sh*t hits the fan you can go back to your comfort zone and continue working as a happy developer and go back to playing after you get your work done.

Dennis
  • 7,907
  • 11
  • 65
  • 115
Chris
  • 11,780
  • 13
  • 48
  • 70
  • While I agree with your points, this is not an answer to the question. It should be posted as a comment (although I'm aware that comments can't accommodate this much text). – Jeff Aug 22 '10 at 00:00
  • 4
    I originally started typing in the comment and ran out of room. :-/ – Chris Aug 22 '10 at 00:02
1

One of the awesome things about Git is that you can easily duplicate your entire working repository. This allows you to preserve a backup copy while you experiment with branching and merging.

My suggested approach for resolving your current issue:

  1. Create a backup copy of your entire repository
  2. Experiment with throw-away copies of the repository
  3. Each time you screw up a throw-away repository -- throw it away and start over with a new copy from your backup
  4. Eventually, you will begin to master repo hacking -- you will have recovered your work, and you will feel good about what you've learned

Also, I hope you are using gitk (or similar) to review the effects of your changes -- it can really help you to visualize the different lines of code and how they are related.

gitk --all ## show me all the branches
Brent Bradburn
  • 51,587
  • 17
  • 154
  • 173