1715

How do I discard the changes to a single file and overwrite it with a fresh HEAD copy? I want to do git reset --hard to only a single file.

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Emiliano
  • 22,232
  • 11
  • 45
  • 59
  • 7
    `git checkout` below is the answer. In git, "revert" is something you do to a commit. "Revert" replays the inverse of a historical commit into your working directory, so you can make a new commit that "undoes" the reverted commit. I find this is a frequent point of confusion for people coming to git from svn. – Dan Ray Aug 22 '11 at 12:34
  • 3
    possible duplicate of [How do I reset/revert a specific file to a specific revision using Git?](http://stackoverflow.com/questions/215718/how-do-i-reset-revert-a-specific-file-to-a-specific-revision-using-git) – freemanoid Dec 30 '13 at 12:20
  • 1
    If you are interested why you cannot do hard reset with paths, check out my answer [there](https://stackoverflow.com/a/46329225/3075942). – user Sep 20 '17 at 19:18
  • This question assumes, that one knows what a Hard reset is. –  Aug 13 '18 at 17:02
  • See also stashing one file: https://stackoverflow.com/questions/3040833/stash-only-one-file-out-of-multiple-files-that-have-changed-with-git?rq=1 – qwr Apr 12 '22 at 07:48
  • `git restore -s main pathTo/MyFile` – guettli Aug 10 '23 at 07:00

9 Answers9

2947

To reset both the working copy of my-file.txt and its state in the Git index to that of HEAD:

git checkout HEAD -- my-file.txt

-- means "treat every argument after this point as a filename". More details in this answer. Thanks to VonC for pointing this out.

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Mark Longair
  • 446,582
  • 72
  • 411
  • 327
  • 79
    More complete answer. +1 ;) For the '--', see also http://stackoverflow.com/questions/6561142/different-between-git-checkout-filename-and-git-checkout-filename (and, more generally, http://stackoverflow.com/questions/1192180/deleting-a-badly-named-git-branch/1192194#1192194) – VonC Aug 22 '11 at 12:19
  • 13
    Also, don't forget you can reference a previous commit with `HEAD~1` to indicate the penultimate commit. – Ryanmt Feb 13 '15 at 22:50
  • 23
    You can leave out `HEAD` if you are at the head of the current branch - see http://www.norbauer.com/rails-consulting/notes/git-revert-reset-a-single-file.html – cxw Jun 08 '15 at 15:41
  • 7
    Any insight why the `reset` command (as it says) "cannot do hard reset with paths", and then why the `checkout` command is not (cannot be?) used for hard-resetting the whole set? (I mean why it has been designed so.) – Sz. Feb 01 '17 at 19:24
  • 2
    @cxw Unfortunately, this is not quite true. From the man page of `git checkout`: "Overwrite paths in the working tree by replacing with the contents in the index or in the ". I.e. if `` is omitted, whatever content in the index will be used to update the working tree. This may or may not differ from HEAD. – tuntap Dec 25 '17 at 11:58
  • 1
    Also, please notice that there is a space between the `--` and the file name. Without the space, git believes that you are passing in a parameter and will give a `error: unknown option` error. – wruckie Mar 22 '19 at 02:50
  • use `git status` you will get: Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git checkout -- ..." to discard changes in working directory) – Paul Han Jun 10 '19 at 02:25
  • Are we sure this is a `hard` reset? After a hard reset on the branch level, all files are reverted to a specific commit without the need for an additional commit. But this method simply applies specific changes from a given commit and requires additional commit. Is there any way to revert to a specific `commit`/`branch` on file level without a need for further commit? – Farid Nov 02 '21 at 09:23
425

Since Git 2.23 (August 2019) you can use restore (more info):

git restore pathTo/MyFile

The above will restore MyFile on HEAD (the last commit) on the current branch.

If you want to get the changes from other commit you can go backwards on the commit history. The below command will get MyFile two commits previous to the last one. You need now the -s (--source) option since now you use master~2 and not master (the default) as you restore source:

git restore -s master~2 pathTo/MyFile

You can also get the file from other branch!

git restore -s my-feature-branch pathTo/MyFile
AxeEffect
  • 6,345
  • 4
  • 37
  • 33
  • 20
    The easiest way so far. Unfortunately this answer is not getting enough attention. – singrium Feb 12 '20 at 10:58
  • 12
    It should be noted that the git documentation still marks this command as **experimental**. – Malhelo Aug 20 '20 at 09:53
  • 3
    `git: 'restore' is not a git command.` git version 2.8.2.windows.1 – Buttle Butkus Oct 29 '21 at 22:32
  • 1
    It’s important to understand that git restore is a dangerous command. Any local changes you made to that file are gone — Git just replaced that file with the last staged or committed version. Don’t ever use this command unless you absolutely know that you don’t want those unsaved local changes. (from the docs) – refaelio Jan 19 '22 at 08:06
  • 9
    @ButtleButkus 2.8 was released 2016-03-28. This answer already mentions it requires 2.23+. – Chris Mar 15 '22 at 13:48
  • 3
    @refaelio Overwriting local changes is the entire point. Is there some other operation that this command might be confused with? – Chris Mar 15 '22 at 13:54
  • Does nothing for me! – jtlz2 May 20 '22 at 12:03
231

Reset to head:

To hard reset a single file to HEAD:

git checkout @ -- myfile.ext

Note that @ is short for HEAD. An older version of git may not support the short form.

Reset to index:

To hard reset a single file to the index, assuming the index is non-empty, otherwise to HEAD:

git checkout -- myfile.ext

The point is that to be safe, you don't want to leave out @ or HEAD from the command unless you specifically mean to reset to the index only.

Asclepius
  • 57,944
  • 17
  • 167
  • 143
  • 4
    What's up with the "--" before myfile.ext? – Lance Kind Jul 24 '17 at 20:34
  • 7
    @LanceKind As I understand, that's used to demarcate a list of filenames which follows it. Without it, there are cases when git interprets the arguments incorrectly. – Asclepius Jul 24 '17 at 23:18
  • 9
    Not just filenames. The widely used convention separates options from positional arguments in many utilities. See `man bash` page. Also mentioned in this answer: https://unix.stackexchange.com/a/187548/142855 – boweeb Apr 25 '19 at 13:37
  • 6
    Conventionally, the `--` is used to tell the program `I've finished specifying "options", and from here on, everything will be a positional argument.`. Conventionally, "options" are the tokens like `--recursive` which can appear in any order, or even be combined together in their short form, like with `rm -rf`. On the contrary, "positional arguments" are much more like arguments passed to a function in a programming language: their *position* in the list of tokens defines what exactly the program is going to do with them (these are often filenames). `--` removes ambiguity as to which is which. – iono Sep 24 '19 at 06:02
  • This is not "hard" resetting anything it just applies changes from some commit and requires additional commit. On branch level hard reset, however, your changes are simply reverted to the commit you wanted to reset to without any additional commit – Farid Nov 02 '21 at 09:24
96

To revert to upstream/master do:

git checkout upstream/master -- myfile.txt
Soviut
  • 88,194
  • 49
  • 192
  • 260
Ann Raiho
  • 1,061
  • 7
  • 3
14

Reference to HEAD is not necessary.

git checkout -- file.js is sufficient

Worthwelle
  • 1,244
  • 1
  • 16
  • 19
10

You can use the following command:

git checkout filename

If you have a branch with the same file name you have to use this command:

git checkout -- filename
Milad Rahimi
  • 3,464
  • 3
  • 27
  • 39
  • 1
    This will not "hard reset" the file - it only copies the index state to the working tree. A "hard reset" would first reset the index. – A.H. Apr 30 '19 at 18:45
8

you can use the below command for reset of single file

git checkout HEAD -- path_to_file/file_name

List all changed files to get path_to_file/filename with below command

git status
HariKishore K
  • 399
  • 3
  • 6
1

You can use the following command:

git reset -- my-file.txt

which will update both the working copy of my-file.txt when added.

ADDYQU
  • 63
  • 5
-29

A simple, easy, hands-on, way to get you out of hot water, especially if you're not so comfortable with git:

  1. View the log of your file

    git log myFile.js

    commit 1023057173029091u23f01w276931f7f42595f84f Author: kmiklas Date: Tue Aug 7 09:29:34 2018 -0400

    JIRA-12345 - Refactor with new architecture.

  2. Note hash of file:

    1023057173029091u23f01w276931f7f42595f84f

  3. Show the file using the hash. Make sure it's what you want:

    git show 1023057173029091u23f01w276931f7f42595f84f:./myFile.js

  4. Redirect file to a local copy

    git show 1023057173029091u23f01w276931f7f42595f84f:./myFile.js > myFile.07aug2018.js

  5. Back up your current file.

    cp myFile.js myFile.bak.js

  6. Open both files in your favorite text editor.

    vim myFile.js
    vim myFile.07aug2018.js

  7. Copy n' paste code from myFile.07aug2018.js to myFile.js, and save.

  8. Commit and push myFile.js

  9. Again view the log, and confirm that your file is properly in place.

  10. Tell your clients to pull the latest, happily watch it work with the old version in place.

Not the sexiest, or most git-centric solution, and definitely a "manual" reset/reversion, but it works. It requires minimal knowledge of git, and doesn't disturb the commit history.

kmiklas
  • 13,085
  • 22
  • 67
  • 103