Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I do a partial revert in GIT

Tags:

git

You can revert the commit without creating a new one by adding the '--no-commit' option. This leaves all the reverted files in the staging area. From there, I'd perform a soft reset and add in the changes I really wanted. For an example workflow:

git revert <sha-of-bad-commit> --no-commit
git reset   // This gets them out of the staging area
<edit bad file to look like it should, if necessary>
git add <bad-file>
git checkout . // This wipes all the undesired reverts still hanging around in the working copy
git commit

You can interactively apply old version of a file using the checkout command.

For example, if you know the COMMIT where the code to add back was removed, you can run the following command:

git checkout -p COMMIT^ -- FILE_TO_REVERT

Git will prompt you to add back the hunks that are missing from the current version of the file. You can use e to create a patch of the change before applying it back.


You can just manually check out the old, good contents of the files you want to revert using git checkout. For instance, if you want to revert my-important-file to the version it was in the version abc123, you can do

git checkout abc123 -- my-important-file

Now you have the old contents of my-important-file back, and can even edit them if you feel like, and commit as usual to make a commit which will revert the changes that he made. If there are only some parts of his commit that you want to revert, use git add -p to select only a few hunks from the patch that you are committing.


I found a way to do this on the Git mailing list:

git show <commit> -- <path> | git apply --reverse

Source: http://git.661346.n2.nabble.com/Revert-a-single-commit-in-a-single-file-td6064050.html#a6064406

Variations

That command fails (causing no changes) if the patch does not apply cleanly, but with --3way you instead get conflicts which you can then resolve manually (in this case Casey's answer might be more practical):

git show <commit> -- <path> | git apply --reverse --3way

You can also use this to partially revert multiple commits, e.g.:

git log -S<string> --patch | git apply --reverse

to revert files with changes matching <string> in any commit. This is exactly what I needed in my use case (a few separate commits introduced similar changes to different files, along with changes other files in unrelated ways that I did not want to revert).

If you have diff.noprefix=true set in your ~/.gitconfig then you need to add -p0 to the git apply command, e.g.

git show <commit> -- <path> | git apply -p0 --reverse