Git Remove One Step in a File's History

103 views Asked by At

I have seen many related discussions, but not an exact resolution to my particular problem. I want to remove one step in the history for a specific file.

So for example, I add a file "Foo.txt". I commit my changes. Then I modify a bunch of files. I commit again. Now, I want to revert "Foo.txt" to an earlier commit, and also delete the history of the changes.

I know that the command

git checkout "aasdfasdfad" Foo.txt

will revert the state of Foo.txt to whatever it was on commit "aasdfasdfad". However, git still has the previous version of "Foo.txt" in its state, somehow. How do I know that? Because in my case, the size of "Foo.txt" changed from a few bytes to a megabyte. So when I revert to the earlier version, the size of my .git directory should go down by about a megabyte, but it doesn't change.

Somehow, I have to tell git that I not only want to revert to an earlier version of Foo.txt, but that I want to throw away all changes to Foo.txt since then.

[added later] Just to make it absolutely clear what I'm trying to do, let me show a very specific scenario:

  1. [create file foo.txt. Now, it is 1KB in size.]
  2. git add foo.txt
  3. [create file bar.txt]
  4. git add bar.txt
  5. git commit -m "small file"
  6. [modify foo.txt. Now it is 1GB in size.]
  7. git add foo.txt
  8. [modify bar.txt]
  9. git add bar.txt
  10. git commit -m "huge file"

At this point, I want to reset foo.txt to the state that it was in after step 3. But I want bar.txt to have the state that it was in after step 8. So I want the files and the history to look as if I had never done steps 6 and 7

1

There are 1 answers

2
David Deutsch On

First of all, I am assuming you know the dangers of rewriting git history - in a nutshell, you don't want to do it if you have already pushed your offending commits to the server and you have other people working on the project.

That being said, you will want to do the following. Make a copy of foo.txt as you wish it to be (i.e., how it was in aasdfasdfad). Then do a git rebase -I aasdfasdfad. This will bring up your editor with a list of commits. For each one that modified foo.txt, change its action from "pick" to "edit". Save and close your editor. Now, every time git pauses the rebase to allow you to edit the commit, copy the "good" version of foo.txt into your working directory (i.e. overwriting the one that git "knows" about). Then git commit --amend, git rebase --continue, and repeat until the rebase is complete.

Note that until garbage collection, your .git directory may remain quite large.