254

I want to revert changes made by a particular commit to a given file only.

Can I use git revert command for that?

Any other simple way to do it?

2
  • Duplicate of stackoverflow.com/questions/215718/… Commented Dec 9, 2016 at 15:15
  • Strange... why the change after all those years? Commented Sep 5, 2017 at 12:08

9 Answers 9

408

The cleanest way I've seen of doing this is described here

git show some_commit_sha1 -- some_file.c | git apply -R 

Show the change and reverse it. Similar to VonC's response but using git show and git apply.

Sign up to request clarification or add additional context in comments.

14 Comments

Nicely done. The script solution is overkill for this. Why can't there just be git revert sha-1 filename ?
This works on my Mac, but on Windows (under Cygwin) it gives me: fatal: unrecognized input
Just a tip, I almost always have to add the -3 flag to git apply for three-way merge when the patch fails, since I am usually correcting a change a bit back in time.
Maybe obvious to most but ensure some_file.c includes the path to the file if there is one otherwise you'll silently patch nothing :)
doesn't work for a binary file. Nevertheless, I copied original file back and did git add/git commit --amend.
|
86

Assuming it is ok to change the commit history, here's a workflow to revert changes in a single file in an earlier commit:

For example, you want to revert changes in 1 file (badfile.txt) in commit aaa222:

aaa333 Good commit aaa222 Problem commit containing badfile.txt aaa111 Base commit 

Rebase on the base commit, amend the problem commit, & continue.

1) Start interactive rebase:

git rebase -i aaa111 

2) Mark the problem commit for edit in the editor by changing pick to e (for edit):

e aaa222 pick aaa333 

3) Revert changes to the bad file:

git show -- badfile.txt | git apply -R 

4) Add the changes & amend the commit:

git add badfile.txt git commit --amend 

5) Finish the rebase:

git rebase --continue 

4 Comments

Just want to point out that this assumes you can edit the git history. Some answers above create a new commit that reverses the particular change without editing the history, which is not always possible/allowed.
Fantastic. This was exactly what I was looking for. I had this idea already, but got confused when doing the interactive rebase that the files when doing the edit was not showing as changed. But the git show -- badfile.txt | git apply -R gave the answer I needed <3
if i understand this git apply -R removes the commit on that file setting it back to the original changed state?
for android studio users, you can right click the file that you want to change, and click rebase and choose the branch that has the good code (probably develop) and click accept theirs to fetch all changes from their and ignore your changes.
32

Much simpler:

git reset HEAD^ path/to/file/to/revert 

then

git commit --amend 

and then

git push -f 

the file is gone and commit hash, message, etc is the same.

2 Comments

For completeness, do you need a git checkout -- path/to/file/to/revert step? Also, it is not true that the hash is the same afterwards, right? The last sentence might be better as something like: "The result is that the last commit is replaced by a new one that differs only in that it does not contain the changes to the reverted file."
@Kevin you're probably right. I'll have to double check that last line, but looking back at this from a couple years ago I'd be surprised if the commit hash is unchanged.
28

If you'd like to reset the changes on a file from your last commit, this is what I'm usually using. I think this is the simplest solution.

Please note that the file will be added to the staging area.

git checkout <prev_commit_hash> -- <path_to_your_file> 

Hope it helps :)

4 Comments

This is the way to go if you aren't looking to rewrite history. I've been using this to cleanup files I didn't really need to touch prior to a squash merge. Then the churn gets paved over anyway.
This will revert all the changes to the file since that commit, not a single commit
Correct words are "previous commit hash" not current commit. Thank you @Gabeeka
This should be the accepted and most rated answer.
24

git revert is for all file contents within a commits.

For a single file, you can script it:

#!/bin/bash function output_help { echo "usage: git-revert-single-file <sha1> <file>" } sha1=$1 file=$2 if [[ $sha1 ]]; then git diff $sha1..$sha1^ -- $file | patch -p1 else output_help fi 

(From the git-shell-scripts utilities from smtlaissezfaire)


Note:

another way is described here if you have yet to commit your current modification.

git checkout -- filename 

git checkout has some options for a file, modifying the file from HEAD, overwriting your change.


Dropped.on.Caprica mentions in the comments:

You can add an alias to git so you can do git revert-file <hash> <file-loc> and have that specific file be reverted.
See this gist.

[alias] revert-file = !sh /home/some-user/git-file-revert.sh 

2 Comments

Just to add to the discussion here, you can add an alias to git so you can do git revert-file <hash> <file-loc> and have that specific file be reverted. I lifted from this answer (though I had to make a couple edits to work correctly). You can find a copy of my .gitconfig and edited script here: gist.github.com/droppedoncaprica/5b67ec0021371a0ad438
@Dropped.on.Caprica good point. I have included it in the answer for more visibility.
13

I would simply use the --no-commit option to git-revert and then remove the files you don't want reverted from the index before finally committing it. Here's an example showing how to easily revert just the changes to foo.c in the second most recent commit:

$ git revert --no-commit HEAD~1 $ git reset HEAD $ git add foo.c $ git commit -m "Reverting recent change to foo.c" $ git reset --hard HEAD 

The first git-reset "unstages" all files, so that we can then add back just the one file we want reverted. The final git-reset --hard gets rid of the remaining file reverts that we don't want to keep.

Comments

11
git reset HEAD^ path/to/file/to/revert/in/commit 

The above command will take file out of commit, but it will reflect in git status.

git checkout path/to/file/to/revert/in/commit 

The above command will revert the changes (as a result you get file same as HEAD).

git commit 

(Pass --amend to amend commit.)

git push 

With this, the file which is already in the commit is removed and reverted.

The above steps should be followed from the the branch where the commit is made.

Comments

8

You can follow this procedure:

  1. git revert -n <*commit*> (-n revert all the changes but won't commit them)
  2. git add <*filename*> (name of the file/s you want to revert & commit)
  3. git commit -m 'reverted message' (add a message for reverting)
  4. after committing discard the other files changes so the files stay updated with the changes you committed before the revert

Comments

1
  1. Start an interactive rebase to modify the latest commit:

    git rebase -i HEAD~1 
  2. Change the pick to edit for the commit you want to modify:

    edit <commit-hash> Your commit message 
  3. Remove the file from the commit while keeping it in the working directory:

    git rm --cached path/to/unwanted_file 

    This command removes the file from the staging area but keeps it in the working directory.

  4. Amend the commit:

    git commit --amend 

    This will open the commit message editor. You can keep the same commit message.

  5. Continue the rebase process:

    git rebase --continue 
  6. Force push the changes to the remote repository:

    git push origin branch-name --force 

I've used those steps a few times, especially when I committed large files I did not want to find in the repo. Be sure to sync with your colleagues as you will have to force push the modified commit that rewrite history

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.