78

Situation:

  1. Edit files
  2. Add files to the index with git add (these files are now "staged")
  3. Edit more files

Now we have three different states: the state of HEAD (which points to the last commit), the state of the index (which includes all added, or "staged" files) and the state of the working tree (the unstaged, local file system state). What is the command to undo changes in the working tree so that it matches the state of the index?

Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
haydenmuhl
  • 5,998
  • 7
  • 27
  • 32
  • 2
    I edited your question to define and make clear what "working tree" and "index" mean, as I've been using `git` for years and only discovered yesterday what these terms mean. I think will help reach many more people, as most of the "populace" using `git` doesn't know these terms, but they do know what their local file system is, what `git add` is, and what green lines (staged content in the index) means when they look at `git status`. Hopefully you're okay with these changes. – Gabriel Staples Mar 11 '21 at 18:20

6 Answers6

85

I tend to use git checkout . which discards all changes from the working directory down. This makes a difference if you're not at the root of the repository.

This command doesn't remove newly created files which is usually a good thing. If you need to do this then you can use git clean as well.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • This also works with a single filenames: `git checkout [file ...]`. Thanks! – naught101 May 28 '12 at 06:46
  • Out of curiosity, do you know how to undo this? – Gershom Maes Feb 01 '16 at 16:26
  • 7
    I find that `git checkout :/` discards all changes in the working tree, regardless of the current working directory. – musiphil Oct 28 '16 at 17:17
  • I've been using git for years and I seem to learn something new every day. I came across this when I needed a file from another branch, so I checked that out. Then edited, and wanted to revert. You can do `git checkout` again without specifying the branch name, it defaults to the state of the index. Nice job. – David Dombrowsky Jan 28 '19 at 20:24
  • @Gershy, you can't undo this. Undoing this would be like undoing `rm some_file`, or undoing a delete where you skipped the trash can. So, make sure it's what you really want before you do this. – Gabriel Staples Mar 11 '21 at 18:22
  • Related: see also [this answer](https://stackoverflow.com/a/12184274/4561887) where these commands are used, and [my answer here too: "How to do a `--soft` or `--hard` git reset by path"](https://stackoverflow.com/a/66539777/4561887) where I use them. – Gabriel Staples Mar 11 '21 at 18:48
  • After a bunch of experimenting, I think `git checkout-index -fa`, [as Peter Tillemans states](https://stackoverflow.com/a/3107826/4561887), produces a much better result. Putting `git clean -fd` into the mix, and providing thorough explanations, led to the creation of [my new answer here](https://stackoverflow.com/a/66589020/4561887). – Gabriel Staples Mar 11 '21 at 20:00
16

You can use git stash save --keep-index to do this. After saving the stash, you can use git stash drop if you don't want to keep it around.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • This is so unintuitive I wonder if I misunderstand something. What I want to do is `git reset --hard ` that has merge conflicts, so that I can just `git pull` the latest version. But git won't let me do that for individual files. Is there really no way to roll back changes to a file in the working directory besides git stash?? – Andy Mar 07 '15 at 02:46
  • 1
    @Andy: To roll back a specific file, `git checkout -- `. – Greg Hewgill Mar 07 '15 at 03:21
  • Oh! I hadn't even thought of that, that's different than other SCMs and GUI tools I'm coming from. Thanks! – Andy Mar 10 '15 at 03:28
12

You can use git-checkout-index (git checkout-index). Be aware that you need to add

  • -f to force it to overwrite existing files, or
  • -f -a to enforce overwriting all paths in the index.
Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
Peter Tillemans
  • 34,983
  • 11
  • 83
  • 114
  • 1
    See `man git checkout-index` for the local man pages. Run `man git` then `/` and type `git-checkout-index`, then Enter, to read a brief blurb about it in the main `man git` pages too. Its description there is "Copy files from the index to the working tree.". – Gabriel Staples Mar 11 '21 at 18:57
  • What's the advantage/difference of this command compared to `git checkout .`? Why is it needed? – Alessandro Dentella Jun 21 '23 at 14:39
12

Use the new git restore command.

Restore the working tree from the index (from staged files):

git restore .

Restore a single file in the working tree from the index (from the staged version):

git restore myFile

source: https://git-scm.com/docs/git-restore

Antoine Weber
  • 1,741
  • 1
  • 14
  • 14
4

git checkout :/ discards all changes in the working tree and replaces it with what's in the index, regardless of the current working directory.

https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefpathspecapathspec

eddygeek
  • 4,236
  • 3
  • 25
  • 32
musiphil
  • 3,837
  • 2
  • 20
  • 26
4

The other answers I don't think capture the full parts. Here's what you need:

Just the commands:

git checkout-index -fa
# See the WARNING below before running this command.
git clean -fd

With detailed comments:

Note: Run git status. Changes shown in green are in your index. These are "staged" changes. Changes shown in red are in your working tree, or local file system, but NOT in the index. These are "unstaged" changes. Calling git checkout-index -fa forces your working tree to match your index, so git status will no longer show those changes in red after running that command, unless it is an entirely new file you have in your working tree, in which case git clean -fd is required to remove/delete it.

# 1. 'f'orce checkout 'a'll paths from the index (staged/added files) to the
# working tree (local file system) 
git checkout-index -fa

# 2. 'f'orce clean (remove) all files and 'd'irectories which are in the working 
# tree but NOT in the index. WARNING WARNING WARNING: this is a destructive
# command and cannot be undone. It is like doing `rm` to remove files. 
# First, make sure no changes exist in red when you run `git status` which
# you want to keep.
git clean -fd

From man git checkout-index:

-f, --force
    forces overwrite of existing files

-a, --all
    checks out all files in the index. Cannot be used together with
    explicit filenames.

See also:

  1. this great help from @Peter Tillemans
  2. my answer where I needed these commands to do a --hard or --soft git reset by path
  3. [my answer, which contains "All about checking out files or directories in git"] How to get just one file from another branch?
Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265