In general, to back out an entire commit, you would use git revert
(as you probably already know). Your issue here is that you want to back out only some of the changes in an older commit. But it turns out this is easy, because:
git revert
has the same effect as applying a patch in reverse (git show
or git diff
with specific commit IDs as needed, and then git apply -R
the resulting patch) and then committing; and
git diff
allows you to choose which file(s) get diff-ed.
So, for a regular (single parent) commit, you can simply:
git show <commit-id> -- <path>
to get the "interesting" change from <commit-id>
, and then pipe (or otherwise feed) the result to git apply -R
:
git show HEAD~3 -- <path> | git apply -R
or in this case:
git show commit2 -- file2.c | git apply -R
For a merge commit, git show
will produce a combined diff, which is not what you want, so you should use git diff
(or git diff-tree
) with two specific commit-IDs. Note that you can inspect the diff before (or after) reverse-applying, since git apply
does not make the new commit itself (so you will have to do that on your own).