Fixing Git repo after incorrect merging
I had a bunch of separate branches, 开发者_Python百科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?
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.
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.
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:
- Create a backup copy of your entire repository
- Experiment with throw-away copies of the repository
- Each time you screw up a throw-away repository -- throw it away and start over with a new copy from your backup
- 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
Mistakes:
- "I started playing with git on my new project"
- "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.
精彩评论