tags:

views:

80

answers:

3

Hi,

I have made 2 commits (And I have not pushed) in git, where 'Commit 2' is the most recent one':

 git log -2
commit 791962d776f66253d656586b097b2677eaa983d1
Author: michael <michael@michael-laptop.(none)>
Date:   Tue Jun 29 23:20:58 2010 -0700

    Commit 2

commit b743075e81f6fe25fe48ddbef2b5e7cc06623533
Author: michael <michael@michael-laptop.(none)>
Date:   Tue Feb 16 23:09:53 2010 -0800

    Commit 1

And in my commit 1 b743075e81f6fe25fe48ddbef2b5e7cc06623533, I touched/changed a number of files:

   dir1/file1.cpp
   dir1/file1.h
   dir1/file2.cpp
   dir1/file2.h

My questions is, how can I roll back my changes that I made to dir1/file2.cpp, dir1/file2.h of commit 1? And keep everything else the same?

Thank you.

+5  A: 

The simplest solution would be, from your latest commit (HEAD) to:

  • checkout those two files at the older version,
  • add them,
  • and then commit.
    git checkout b743075e81 -- dir1/file2.cpp
    git checkout b743075e81 -- dir1/file2.h
    git add dir1/file2.cpp # only if you made additional changes
    git add dir1/file2.h   # only if you made additional changes
    git commit -m "revert dir1/file2.cpp and dir1/file2.h"

As Chris Johnsen mentions in the comments:

git checkout with pathspecs updates the index (like git reset with pathspecs) and the working tree, so git add is not needed unless additional changes are made after the checkout.

VonC
This is in fact your only sane option, if you've already used `git push` to push your commits to the origin.
Blair Holloway
*git checkout* with pathspecs updates the index (like *git reset* with pathspecs) and the working tree, so *git add* is not needed unless additional changes are made after the checkout.
Chris Johnsen
I have not do a 'git push'.
michael
@michael: then the `git rebase --interactive` described in Blair's answer should interest you.
VonC
A: 

Use following command to roll back the file with previously committed file based on the commit hash and filename which you need to revert

 git reset <commit hash> <filename>

For your requirement use

 git reset b743075e81f6fe25fe48ddbef2b5e7cc06623533 dir1/file2.cpp

 git reset b743075e81f6fe25fe48ddbef2b5e7cc06623533 dir1/file2.h
YetAnotherCoder
This works, but can be confusing because it only “rolls back” the index entries, not the working tree (unlike `git checkout treeish -- pathspecs` which updates both the index and the working tree).
Chris Johnsen
+3  A: 

If you've already pushed your commits to the origin, then the other solutions described here (using git reset or git checkout, followed by git commit) is your only sane option.

However, if you haven't pushed your changes yet, and you want to remove all traces that the files were ever committed, an interactive rebase is a good option. Use the following command to rebase your last two commits:

git rebase --interactive HEAD~2

An editor will open, showing your two commits. You want to edit the file to show the following, then save; particularly, you want to change pick in front of your first commit to edit:

edit b743075 Commit 1
pick 791962d Commit 2

Git will then place us into a state where we can edit the first commit (without touching the second). It says you can amend the commit with git commit --amend, but we actually want to do a reset to the commit before head, and undo it entirely:

git reset HEAD^

This will place the changes from Commit 1 back into your working tree. Then, git add only the files you want to keep, and re-commit them using git commit:

git add dir1/file1.cpp
git add dir1/file1.h
git commit -m "Commit 1"

Finally, do a hard reset to delete the files you don't want to keep from your working tree, and finish the rebase:

git reset --hard
git rebase --continue

When the rebase is complete, your repository will have both commits, but no traces of the file2.* files.

Blair Holloway