Can I do a partial revert in GIT
Is it possible to revert only a single file or certain changes in a file in multi file commit?
Full story I committed a bunch of files. A number of commits later someone who will remain nameless (JACK!!!) copied a file into his repository and committed several files, overwriting some of the changes I did. I want to revert the one file that got clobbered or better yet, go in and revert two changes in that file. This will have to be a separate rever开发者_StackOverflow社区t commit since it was pulled and pushed.
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 mixed reset (the default for reset) to un-stage the files, and add in the changes I really wanted. Then, commit, (you can add and commit more files if you want multiple commits), and finally, checkout the current directory to wipe out any uncommitted and un-staged modifications resulting from the revert
. 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 commit
git checkout . # This wipes all the undesired reverts still hanging around in the working copy
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
精彩评论