开发者

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜