tags:

views:

43

answers:

2

I have a git repository that I am using and I've screwed up. I made a few patches to the source tree and then went on to do upgrades without committing the patches first. Then I committed the whole batch together as one. My intent was to be doing the upgrades on a separate branch, which I did create before the commit.

Now at this point I have two (relevant) branches master, which is still stable but needs patched. And I have new_auth_system which has two commits ahead of master. The first is full of patches I did yesterday and committed. The second has a few more patches and an incredibly large and obscure amount of deletions and additions across several files.

I've been trying to use git checkout to pull the specific files out of the commit and tack them onto a clone of master in an attempt to get things corrected but I keep getting "fatal: reference is not a tree"

How do I go about pulling specific files across commits and into another branch?

Thanks!

A: 

I'm a little confused by your question, so please let me know if my response isn't appropriate.

From what I understand, you want to roll back specific files to a specific commit. To do that:

Use git log to grab the version (hash) you're looking for:

git log -p filename

Once you have the version (hash), use git checkout to revert that file:

git revert --no-commit version
labratmatt
Its a bit more complicated than that, I think. VonC has the right idea of whats going on and even has a nice little picture that describes exactly what I imagine to be the case.
+1  A: 

If your situation is:

 x--x--x--x (master, need patch)
        \
         y1--y2  new_auth_system, with y1 containing some patches *and* updates
                                  and y2 containing massive refactoring

I would recommand first:
(if you haven't pushed new_auth_system already)

  • a rebase --interactive to split y1 into y1a (with only your patches) and y1b (updates), and y2 in y2a (more patches) and y2b (massive refactoring)
    git checkout new_auth_system
    git rebase -i y1^

     x--x--x--x (master, need patch)
            \
             y1a--y1b--y2a--y2b  new_auth_system, with y1a containing only patches
                                                       y1b containing only updates
                                                       y2a containing only patches
                                                       y2a containing refactoring
  • a rebase --interactive to reorder 'y' commits (patches first, updates and refactoring second)
    git checkout new_auth_system
    git rebase -i y1a^

     x--x--x--x (master, need patch)
            \
             y1a--y2a--y1b--y2b  new_auth_system, with patches first (y1a, y2a)
                                                       updates and refactoring second
  • a git merge to integrate those patches in master:
     x--x--x--x------x' (master, with patches)
            \       /
             y1a--y2a--y1b--y2b  new_auth_system, with patches first, 
                                                       updates and refactoring second

It is better than trying to isolate some files from one branch to another: Git reasons in term of project (a collection of files under a common tree), not in term of individual files.

VonC
Thanks for your response.Okay, so thats exactly what I am hoping to do. Except I pushed the changes to the server already. I'm the only one using the git repo, so its not possible that someone would have pulled since it was pushed though. Is it still a bad idea to rebase like this?
@Robert: no it is not a bad idea, since you can `git push -f` your way out of this situation, effectively replacing the previous history of commits already pushed by that new history. Since you are the only one using that repo, no one will "suffer" from this push.
VonC
Okay. I'm all for this....and I tried it and failed. Apparently I'm not entirely sure how to use git rebase interactive. Somehow I deleted a commit entirely. Not to worry. I renamed the local repo to another directory and cloned the remote again so I'm back where I started. Is there a tutorial or screencast out there on rebase that covers the style of rebasing? I searched for 'git rebase -i' but all I can find are "the benefits of rebasing vs merging" tutorials.
@Robert: some good links/introductions: http://www.gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html, http://gitcasts.com/posts/rebasing, http://codeutopia.net/blog/2009/12/10/git-interactive-rebase-tips/ (for breaking a commit in two). Off course, the principle for splitting commits is right in the man page: http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html#_splitting_commits, also described at the end of Git Book: http://book.git-scm.com/4_interactive_rebasing.html.
VonC
@VonCThanks so much. I read through a bunch of the documentation you linked and was able to figure out what was going on with interactive rebase (and several other git things as well). I'm all fixed up and ready to go now!Thanks again!ROB
@Robert: glad to read you have managed to use those commands, that is great! You might also consider leaving an "answer" in this question page, detailing the steps you followed, for other to have an illustration of this "official" answer.
VonC