34

I'm wondering if there is a way to quickly reverse specific hunk of a commit.

I can generate a diff between two commits or HEAD to see the difference.

How do I reverse just one of those hunks (or better yet, a set of specific hunks)?

smci
  • 26,085
  • 16
  • 96
  • 138
dkinzer
  • 28,835
  • 12
  • 63
  • 79

4 Answers4

44
git checkout -p $REF -- path/to/file

e.g.,

git checkout -p HEAD^ myfile

Where $REF is a ref name or commit ID that specifies the commit you want to take the file state from. For example, to selectively revert changes made in the last commit, use HEAD^.

Rob Bednark
  • 19,968
  • 18
  • 67
  • 100
cdhowie
  • 133,716
  • 21
  • 261
  • 264
  • 6
    More precisely, that will let you selectively check out versions of content from the previous commit; changes between your current commit and the work tree will also be discarded. – Cascabel Nov 22 '10 at 17:32
  • 2
    Yes I've done this that before. But this reverts back all the changes? I'm looking to revert back only some of the changes. – dkinzer Nov 22 '10 at 17:32
  • 2
    @DKinzer: No, the `-p` option will let you interactively select hunks to apply to your working tree. – cdhowie Nov 22 '10 at 17:33
  • 4
    No problem. Note that a lot of git commits (`add`, `checkout`, `reset`, etc.) will take the `-p` option this way and will let you pick which hunks to act on. This is really handy when two hunks in the same file should go into different commits. – cdhowie Nov 22 '10 at 17:36
  • 1
    I'm new to git and so far only knew about -i for selectively choosing commits when doing a rebase. I think the -p option will be very useful to me. – dkinzer Nov 22 '10 at 17:38
  • In order to remove hunks, select `y` when prompted for each hunk. This will produce a staged diff on top of your previous commit without modifying it. You can then view the diff by unstaging it (`git reset `) then `git diff`. Finally, you can merge it into your previous commit via `git commit --amend `). – Nick Desaulniers Apr 03 '20 at 21:50
1
git difftool $REF -- /path/to/file

where $REF is a ref name or commit ID that specifies the commit you want to take the file state from. For example, to selectively revert changes made in the last commit, use HEAD^.

This question was already answered by @cdhowie, but I find it somewhat nicer to use an interactive difftool like meld to selectively restore old hunks/lines of code, especially if there is a newly-introduced, hard-to-find bug in the code.

erik
  • 2,058
  • 1
  • 21
  • 30
0

To recover a deleted file from a previous commit I used the answer here:

Find and restore a deleted file in a Git repository

git checkout <deleting_commit>^ -- <file_path>
Community
  • 1
  • 1
John Naegle
  • 7,678
  • 3
  • 33
  • 47
0

To revert one or more hunks from specific commit(s) do like this - using add -p in essence:

git revert --no-commit <commit>…​ 
git reset                              # unstage things
git add -p [OPTIONS] [<pathspec>…​]     # choose hunks interactively
git restore .                          # wipe the rest (in root directory)
... maybe further changes ...
git commit [--fixup] ...

Future git versions may support git revert -p directly...

Note: Methods like git checkout/restore -p ... do not consistently revert hunks from a specific commit but go to pick parts from a certain file state - possibly loosing changes in other later commits.

kxr
  • 3,041
  • 30
  • 20