Reputation: 47
I think my question is close to this one, but I'm using git.
So, let's say I have
Commit1 changed file1.c and file2.c
Commit2 changed file2.c, file3.c, file4.c
Commit3 changed file1.c , file2.c and file3.c
and so on...
Then, I would like to revert only the changes that Commit2 made in file2.c, but, try to keep the changes that Commit3 made in this file...
What you think? There is some way to do it?
Thank you.
Upvotes: 4
Views: 2418
Reputation: 487725
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; andgit 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).
Upvotes: 5
Reputation: 17455
You may try to revert Commit2 (that is, apply a new git commit, whose changes would be opposite to the changes made in Commit2) but without committing. There's a instant menu entry in gitk
for example. In this new commit you leave only changes made to file2
and commit the result.
Alternatively, you could simply do something like
git diff Commit2..Commit1 -- file2.c > revert.patch
git apply revert.patch
it might be useful to take a look on the patch before applying it because commits after Commit2 may introduce some conflicts with the changes to file2.c
from Commit2.
Upvotes: 4
Reputation: 2409
Do you want to do revert
?
Or just want to modify it. If so, you can do it with
git rebase -i HEAD^^
Next, an editor will open. In the editor modify 'pick' to 'edit' on Commit2 like
pick abcdefg Commit3
pick jikdvuf Commit2
to
pick abcdefg Commit3
edit jikdvuf Commit2
Then, you can modify your commit. So now modify the file. You may want to do git checkout FILENAME
. After that
git add FILENAME
git rebase --continue
Now you successfully modified the file on Commit2.
Upvotes: 1