Selectively revert or checkout changes to a file in Git?
GitGit Problem Overview
Is there a command that allows you to partially undo the changes to a file (or files) in the working directory?
Suppose you have edited a file a lot but you realize that you want to undo some of the changes back to the committed state, but not the other changes.
I'm envisioning an option for git checkout
that works a lot like git add -p
, i.e. it goes through the file hunk by hunk and asks if you want to keep it or not.
Git Solutions
Solution 1 - Git
With git version >= 1.7.1 I can
git checkout -p
I am not sure when this feature was introduced.
Solution 2 - Git
You could use
git add -p <path>
to stage the chunks that you want to keep in a particular file, then
git checkout -- <path>
to discard the working tree changes that you didn't want to keep, by checking out the staged version of the file.
Finally, you can use
git reset -- <path>
to revert the staged version of the file to the most recent committed version of the file to leave you with your changes unstaged.
Solution 3 - Git
git checkout $file
reverts the state of the file $file
to the last committed state. I think you can use git checkout SHA-1 -- $file
to revert the file to the commit identified by SHA-1.
Solution 4 - Git
How many commits do you need to go back and select from? If it's just one, maybe take a branch just before it, checkout the file you committed and then use git add -p
to add it how you wanted it. Then you can go back to where you were and checkout the file from your temp branch.
that is:
git checkout -b temp troublesome-commit^
git checkout troublesome-commit -- path/to/file
git add -p path/to/file
git commit -c troublesome-commit
git checkout @{-1}
git checkout temp -- path/to/file
git commit path/to/file
git branch -D temp
Other alternatives include going back and editing the commit with git rebase -i
(marking the commit as edit
, then doing a git reset HEAD^
and redoing the commit when dropped back into the shell).
If the changes you need to select from are spread over a series of commits, it may be better to extract them as patches (or a patch covering all of them) and hand-edit the patch, taking out the changes you want to keep, and feeding the residual into git apply --reverse
.