Posted By: Anonymous
I was working with a friend on a project, and he edited a bunch of files that shouldn’t have been edited. Somehow I merged his work into mine, either when I pulled it, or when I tried to just pick the specific files out that I wanted. I’ve been looking and playing for a long time, trying to figure out how to remove the commits that contain the edits to those files, it seems to be a toss up between revert and rebase, and there are no straightforward examples, and the docs assume I know more than I do.
So here is a simplified version of the question:
Given the following scenario, how do I remove commit 2?
$ mkdir git_revert_test && cd git_revert_test $ git init Initialized empty Git repository in /Users/josh/deleteme/git_revert_test/.git/ $ echo "line 1" > myfile $ git add -A $ git commit -m "commit 1" [master (root-commit) 8230fa3] commit 1 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 myfile $ echo "line 2" >> myfile $ git commit -am "commit 2" [master 342f9bb] commit 2 1 files changed, 1 insertions(+), 0 deletions(-) $ echo "line 3" >> myfile $ git commit -am "commit 3" [master 1bcb872] commit 3 1 files changed, 1 insertions(+), 0 deletions(-)
The expected result is
$ cat myfile line 1 line 3
Here is an example of how I have been trying to revert
$ git revert 342f9bb Automatic revert failed. After resolving the conflicts, mark the corrected paths with 'git add <paths>' or 'git rm <paths>' and commit the result.
The algorithm that Git uses when calculating diff’s to be reverted requires that
- the lines being reverted are not modified by any later commits.
- that there not be any other “adjacent” commits later in the history.
The definition of “adjacent” is based on the default number of lines from a context diff, which is 3. So if ‘myfile’ was constructed like this:
$ cat >myfile <<EOF line 1 junk junk junk junk line 2 junk junk junk junk line 3 EOF $ git add myfile $ git commit -m "initial check-in" 1 files changed, 11 insertions(+), 0 deletions(-) create mode 100644 myfile $ perl -p -i -e 's/line 2/this is the second line/;' myfile $ git commit -am "changed line 2 to second line" [master d6cbb19] changed line 2 1 files changed, 1 insertions(+), 1 deletions(-) $ perl -p -i -e 's/line 3/this is the third line/;' myfile $ git commit -am "changed line 3 to third line" [master dd054fe] changed line 3 1 files changed, 1 insertions(+), 1 deletions(-) $ git revert d6cbb19 Finished one revert. [master 2db5c47] Revert "changed line 2" 1 files changed, 1 insertions(+), 1 deletions(-)
Then it all works as expected.
The second answer was very interesting. There is a feature which has not yet been officially released (though it is available in Git v1.7.2-rc2) called Revert Strategy. You can invoke git like this:
git revert –strategy resolve <commit>
and it should do a better job figuring out what you meant. I do not know what the list of available strategies is, nor do I know the definition of any strategy.