使用 Git,如何将工作树(本地文件系统状态)重置为索引(已暂存的文件)的状态?

78

情况:

  1. 编辑文件
  2. 使用git add将文件添加到索引中(这些文件现在被“暂存”)
  3. 编辑更多文件

现在我们有三个不同的状态:HEAD状态(指向最后一次提交),索引状态(包括所有已添加或“暂存”的文件)和工作树状态(未暂存,本地文件系统状态)。如何撤销工作树中的更改,以使其与索引状态匹配?

答案:使用命令 git reset 与选项--hard,它会重置工作树的状态以匹配索引状态。

2
我编辑了你的问题,定义并澄清了“工作树”和“索引”的含义,因为我使用git已经有很多年了,但直到昨天才发现这些术语的含义。我认为这将有助于更多人理解,因为大多数使用git的人不知道这些术语,但他们知道什么是本地文件系统,知道git add是什么,以及当他们查看git status时绿色行(索引中的暂存内容)的含义。希望你对这些改变感到满意。 - Gabriel Staples
6个回答

85

我倾向于使用git checkout .命令,它会放弃工作目录及以下的所有更改。如果您不在存储库的根目录下,这将产生差异。

此命令不会删除新创建的文件,通常这是一件好事。如果您需要执行此操作,则还可以使用git clean命令。


出于好奇,你知道如何撤销这个操作吗? - Gershom Maes
7
我发现 git checkout :/ 会放弃工作树中所有的更改,而不考虑当前的工作目录。 - musiphil
我已经使用Git多年了,似乎每天都能学到新东西。当我需要从另一个分支获取文件时,我遇到了这个问题,所以我切换到了那个分支。然后进行了编辑,并想要还原。你可以再次使用git checkout而不指定分支名称,它会默认返回索引的状态。干得好。 - David Dombrowsky
相关:请参阅此答案,其中使用了这些命令,以及我的答案:“如何通过路径执行--soft--hard git reset”中我使用它们。 - Gabriel Staples
经过一系列的尝试,我认为git checkout-index -fa(正如Peter Tillemans所说)可以产生更好的结果。将git clean -fd加入其中,并提供详细的解释,导致了我在这里创建了新的答案。 - Gabriel Staples
显示剩余2条评论

16
你可以使用 git stash save --keep-index 来实现这个目的。保存好储藏后,如果你不想要它了,可以使用 git stash drop 去除它。

这太不直观了,我在想是否有什么地方误解了。我想要做的是 git reset --hard <specific file>,但这个文件有合并冲突,因此我只能git pull最新版本。但是git不允许我为单个文件执行此操作。除了git stash之外,难道真的没有回滚工作目录中文件更改的方法吗? - Andy
1
@Andy:要回滚特定文件,请使用 git checkout -- <specific file> 命令。 - Greg Hewgill
哦!我甚至没有想到那个,这与我之前使用的其他SCM和GUI工具不同。谢谢! - Andy

13

使用新的git restore命令。

从索引(已暂存文件)中还原工作树:

git restore .

从索引中还原工作树中的单个文件(从暂存版本):

git restore myFile

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


1
这应该是被选中的答案。 - Dan Stevens

12

你可以使用git-checkout-indexgit checkout-index)命令。请注意,你需要添加

  • -f 选项以强制覆盖现有文件,或者
  • -f -a 选项以强制覆盖索引中的所有路径。

1
请查看本地手册页man git checkout-index。运行man git,然后输入/git-checkout-index,然后按Enter键,在主man git页面中阅读有关它的简短介绍。在那里的描述是“将文件从索引复制到工作树”。 - Gabriel Staples
这个命令与git checkout .相比有什么优势/区别?为什么需要它? - Alessandro Dentella

4
其他答案我认为没有完全涵盖所有部分。以下是你需要的内容:
只有命令:
git checkout-index -fa
# See the WARNING below before running this command.
git clean -fd

带有详细注释:

注意:运行 git status 命令。显示为 绿色 的更改位于你的 索引 中。这些是“已暂存”的更改。显示为 红色 的更改位于你的 工作树 或本地文件系统中,但不在 索引 中。这些是“未暂存”的更改。调用 git checkout-index -fa 命令会强制使你的 工作树 与你的 索引 相匹配,因此在运行该命令后,git status 不再以红色显示这些更改,除非它是你的工作树中的一个全新的文件,这种情况下需要使用 git clean -fd 命令来移除/删除它。

# 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

来自于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.

另请参阅:

  1. 这位来自@Peter Tillemans的巨大帮助
  2. 我的答案,其中我需要使用这些命令进行按路径进行--hard--soft git重置
  3. [我的答案,其中包含"有关在git中检出文件或目录的全部信息"] 如何从另一个分支获取一个文件?

4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接