如何丢弃 Git 中未暂存的更改?

git version-control

如何丢弃工作副本中不在索引中的更改?

git-clean 仅从工作树中删除未跟踪的文件 git-scm.com/docs/git-clean

为了澄清 Asenar 的上述评论,git-clean -df 可能很危险。它将删除本地未跟踪的文件(例如,由 .gitignore 覆盖)仔细阅读以下所有内容并考虑 git checkout 。反而

'git clean -df' 被警告!我试过了,但丢失了无法恢复的关键文件夹……哎呀!

点击 git status 会给出如何做到这一点的建议! git checkout -- .

@Paulo:从 2019 年 7 月开始,git status 给出了建议:git restoregit restore 正是用于此目的的新命令。请参阅my 2019 update

N
Nagev

对于当前工作目录中的所有未暂存文件,请使用:

git restore .

对于特定文件使用:

git restore path/to/file/to/revert

它与 git switch 一起替换了重载的 git checkout (see here),从而消除了参数消歧。

如果文件同时具有暂存更改和未暂存更改,则仅还原 git diff 中显示的未暂存更改。 git diff --staged 中显示的更改保持不变。

在 Git 2.23 之前

对于当前工作目录中的所有未暂存文件:

git checkout -- .

对于特定文件:

git checkout -- path/to/file/to/revert

-- 用于消除歧义(这称为 argument disambiguation)。

这似乎是 git 规范的方式。即如果你输入 git status

如果有未跟踪的文件,则不起作用。 Git 说 error: The following untracked working tree files would be overwritten by checkout: ...

新手问题,“git checkout -- ”是什么意思?语义上的意思?

@Ninjack git checkout -- .git checkout . 的含义相同,只是您明确表示您没有指定分支名称。他们都说在我目前正在为“。”的分支上检查 HEAD 版本。或者 '。/'。如果您通常执行 git checkout branch-name directory-or-file-name,则会在分支 branch-name 上获得 directory-or-file-name 的 HEAD 版本。

IMO 这个变体是不完美的,因为它无法处理更改清理时更改的存储库不在 HEAD 修订版上并且您不想将其更新为 HEAD 并且只想清理更改的情况。

B
Brandon Minnick

另一种更快的方法是:

git stash save --keep-index --include-untracked

如果您不想详细说明,则无需包含 --include-untracked

之后,您可以根据需要使用 git stash drop 命令删除该存储。

@KarimSamir:该问题专门询问不在索引中的更改。 git reset 命令也将丢弃索引中的更改。

混帐结帐 - 。快得多

git stash 和任何种类的 git checkout 都不会丢弃未暂存的删除。根据git status的输出,这里的实际正确答案是有点味道git reset HEAD

这会污染存储堆栈。 git checkout -- . 只用一个命令完成这项工作。

@FelipeTonello 我希望我能给你 100 个代表该评论。在我的测试中,这似乎正是我想要的。相反,我花了最后一个小时使用“git checkout -- *”并解决所有未跟踪的文件错误。

L
Laurel

似乎完整的解决方案是:

git clean -df
git checkout -- .

警告:虽然它不会删除 .gitignore 中直接提及的被忽略文件,但git clean -df 可能会删除文件夹中的被忽略文件

git clean 删除所有未跟踪的文件,git checkout 清除所有未暂存的更改。

其他两个答案实际上不起作用,这个起作用了。

@dval 这是因为第一个命令删除了未索引的文件,第二个命令删除了未暂存的更改(索引文件)。因此,如果您没有任何阶段性更改,这与使用 git reset --hard 恢复到上次提交相同

如果未跟踪的目录是 git 克隆,请使用 -dff。

小心运行 git clean -df。如果你不明白它的作用,你可能会删除你想要保留的文件,比如 robots.txt、上传的文件等。

正如@ctlockey 所说,如果目录仅由被忽略的文件组成,第一个命令也会删除目录......在我的项目中丢失了一大堆配置文件:(小心。

C
CB Bailey

这将检查当前目录的当前索引,从当前目录向下丢弃文件中的所有更改。

git checkout .

或者这个从索引中检查所有文件,覆盖工作树文件。

git checkout-index -a -f

+1 这是正确的答案,因为它正确处理了某些文件同时具有暂存 未暂存更改的情况。请注意,此解决方案会丢弃未暂存的更改;如果您希望保留它们,那么您应该使用 @greg-hewgill 的 git stash save --keep-index 答案。

如果您只有一个分支,git checkout -- 将不起作用。 git checkout . 始终有效。

太感谢了!最后一个总是有效的答案!这可以与 git clean 结合使用以删除未跟踪的文件。

不好笑,但这似乎是唯一可行的答案。评分较高的答案似乎无济于事。我确信他们会做一些事情,但他们当然不会“重置”未分级的更改。

f
falsarella
git clean -df

从当前目录开始,通过递归删除不受版本控制的文件来清理工作树。

-d:除了未跟踪的文件之外,还删除未跟踪的目录

-f:强制(根据 clean.requireForce 设置可能不需要)

运行 git help clean 查看手册

为什么这个答案没有得到所有的选票?在 2011 年回答,仍然正确。

这应该是公认的答案。

p
prosoitos

2019 年更新

您现在可以通过以下方式丢弃一个跟踪文件中的未暂存更改:

git restore <file>

并在当前目录(递归)中的所有跟踪文件中:

git restore .

如果您从存储库的根目录运行后者,它将丢弃项目中所有跟踪文件中的未暂存更改。

笔记

git restore 于 2019 年 7 月推出,并在 2.23 版中发布,作为 git checkout 命令拆分为文件的 git restore 和分支的 git switch 的一部分。

git checkout 仍然像以前一样运行,旧的答案仍然完全有效。

当在工作树中运行 git status 且未暂存更改时,现在这是 Git 建议用来丢弃它们的方法(而不是 git checkout -- ,因为它过去在 v2.23 之前)。

与 git checkout -- . 一样,这只会丢弃跟踪文件中的更改。所以 Mariusz Nowak 的回答仍然适用,如果您想丢弃所有未暂存的更改,包括未跟踪的文件,您可以按照他的建议运行额外的 git clean -df。

我只想在不影响新添加的文件的情况下恢复我未暂存的更改,因此 git restore . 可以完美运行。谢谢。

我做了git restore <filename>,效果很好。

对我来说工作得很好。

根据手册页 git restore . 恢复当前目录中的所有文件,而不是整个存储库。

你说的对。谢谢!我刚刚测试了它,确实是这样。然而,它是递归的。因此,当从项目的根目录运行时,它适用于整个存储库。我将编辑我的答案。

B
Ben

我最喜欢的是

git checkout -p

这使您可以有选择地还原块。

也可以看看:

git add -p

我喜欢在丢弃之前看到实际变化的能力。

这就是我使用的。 git checkout -p 然后“a”接受所有。

我从来没有想过。 -p 增加了一个很好的额外安全层。将其与 git clean -d 结合以实际回答 OP。

E
ErikMD

由于没有答案表明我使用的确切选项组合,这里是:

git clean -dxn .  # dry-run to inspect the list of files-to-be-removed
git clean -dxf .  # REMOVE ignored/untracked files (in the current directory)
git checkout -- . # ERASE changes in tracked files (in the current directory)

这是所用 git clean 选项的在线帮助文本:

-d

除了未跟踪的文件之外,还删除未跟踪的目录。如果未跟踪的目录由不同的 Git 存储库管理,则默认情况下不会将其删除。如果您真的想删除这样的目录,请使用 -f 选项两次。

-x

不要使用从 .gitignore(每个目录)和 $GIT_DIR/info/exclude 读取的标准忽略规则,但仍要使用通过 -e 选项给出的忽略规则。这允许删除所有未跟踪的文件,包括构建产品。这可以用来(可能与 git reset 结合使用)创建一个原始工作目录来测试一个干净的构建。

-n

实际上不要删除任何东西,只是显示将要做什么。

-f

如果 Git 配置变量 clean.requireForce 未设置为 false,Git clean 将拒绝删除文件或目录,除非给定 -f-n-i。 Git 将拒绝删除 .git 子目录或文件中的目录,除非给出第二个 -f

对此解决方案 +1。关于您所说的“git checkout。需要在回购的根目录中完成”,也许您可能会提到我们可以只做git reset --hard? (这实际上等同于 git reset --hard HEAD 并且应该适用于当前目录......)

同样关于第一个命令 git clean -dfx,这是我在运行它之前使用的安全方面的提示:只需运行 git clean -d -x -n 之前,显示要删除的文件列表,然后通过以下方式确认操作运行 git clean -d -x -f(我将参数 -n-f 放在最后,以便能够在终端中快速更改它)

请注意,这是不可逆的,如果您在 .gitignore 中有文件,您将丢失它们。因此,请考虑在此之前备份您的项目。

@MartinG 我只是借此机会合并了我的 two suggestions,包括添加“试运行”步骤的那个(安全总比抱歉好!)。无论如何,如果需要,请随时修改我的编辑!

如何删除出现在 git status 中的未跟踪文件而不删除 .gitignore 中的未跟踪文件?

2
2540625

如果您只想删除对现有文件的更改,请使用 checkout (documented here)。

git checkout -- .

没有指定分支,所以它检查出当前分支。

双连字符 (--) 告诉 Git 应该将后面的内容作为它的第二个参数(路径),即您跳过了分支的规范。

句点 (.) 表示所有路径。

如果您希望删除自上次提交后添加的文件,请使用 clean (documented here):

git clean -i 

-i 选项启动交互式清理,以防止错误删除。

还有一些其他选项可用于更快地执行;请参阅文档。

如果您希望将更改移动到保留空间以供以后访问,请使用 stash (documented here):

git stash

所有更改都将移至 Git 的 Stash,以供以后访问。

有一些选项可用于更细微的存储;请参阅文档。

这将完全转换您的更改并丢弃先前提交中新添加的文件。

它会删除新添加的文件吗?或者只是撤消旧未暂存文件中的更改?

F
Forhadul Islam

最简单的方法是使用以下命令:

此命令用于丢弃工作目录中的更改 -

git checkout -- .

https://git-scm.com/docs/git-checkout

在 git 命令中,未跟踪文件的存储是通过以下方式实现的:

git stash -u

http://git-scm.com/docs/git-stash

我来过这里两次,阅读了这个答案,最后忘记了 .。对未来的我:这个时期是必不可少的

我需要摆脱子目录中的所有本地更改,而不会消除所有其他更改。这个答案很有帮助,谢谢

请描述这两个命令的作用。没有解释真的没用。

出色的。结帐在一个命令中执行最流行的命令在两个命令中执行的操作。也可以用 git clean -fd 来清理不在索引中的文件。

f
fontno

我真的发现这篇文章有助于解释何时使用什么命令:http://www.szakmeister.net/blog/2011/oct/12/reverting-changes-git/

有几种不同的情况:

如果您尚未暂存文件,则使用 git checkout。签出“更新工作树中的文件以匹配索引中的版本”。如果文件还没有被暂存(也就是添加到索引中)......这个命令基本上会将文件恢复到你上次提交的状态。 git checkout -- foo.txt 如果你已经暂存了文件,那么使用 git reset。重置更改索引以匹配提交。 git reset -- foo.txt

我怀疑使用 git stash 是一种流行的选择,因为它的危险性要小一些。如果您在使用 git reset 时不小心吹走太多东西,您可以随时返回它。默认情况下,重置是递归的。

请查看上面的文章以获取更多建议。

J
Joshua Kunzmann

如果您对保留未暂存的更改不感兴趣(特别是如果暂存的更改是新文件),我发现这很方便:

git diff | git apply --reverse
D
Dorian

当您键入 git status 时,(使用“git checkout -- ...”放弃工作目录中的更改)会显示。

例如git checkout -- .

否决,因为它无助于快速丢弃所有文件。三个点表示您需要列出所有文件。如果您需要一次丢弃大量文件,这尤其糟糕,例如。在您完成所有想要保留的修改后的大型合并期间

当然,正确的命令是“git checkout --”。一个点。在评论中,三个点是语法上的东西,表示可以使用许多其他选项。

A
Asped

您可以使用 git stash - 如果出现问题,您仍然可以从 stash 中恢复。与此处的其他答案类似,但此答案也删除了所有未暂存的文件以及所有未暂存的删除:

git add .
git stash

如果您检查一切正常,请将藏匿处扔掉:

git stash drop

Bilal Maqsood 与 git clean 的答案也对我有用,但有了存储,我有更多的控制权——如果我不小心做了某事,我仍然可以取回我的更改

更新

我认为还有1个变化(不知道为什么这对我有用):

git add . -A 而不是 git add .

如果没有 -A,将不会暂存已删除的文件

B
Bijan

git checkout -f

man git-checkout

-f, --force

切换分支时,即使索引或工作树与 HEAD 不同,也要继续。这用于丢弃本地更改。

从索引中检出路径时,不要在未合并的条目上失败;相反,未合并的条目将被忽略。

这将丢弃索引中的更改! (并且 OP 要求保持原样。)

N
Nick

我没有放弃更改,而是将遥控器重置为原点。注意 - 此方法是将您的文件夹完全恢复到存储库的文件夹。

所以我这样做是为了确保当我 git reset 时它们不会坐在那里(稍后 - 不包括 Origin/branchname 上的 gitignores)

注意:如果您想保留尚未跟踪的文件,但不在 GITIGNORE 中,您可能希望跳过此步骤,因为它将擦除在您的远程存储库中找不到的这些未跟踪文件(感谢@XtrmJosh)。

git add --all

然后我

git fetch --all

然后我重置为原点

git reset --hard origin/branchname

这将使它回到原点。就像重新克隆分支一样,同时将我所有的 gitignored 文件保存在本地和适当的位置。

更新了下面的每个用户评论:将 重置为用户所在的任何当前分支的变体。

git reset --hard @{u}

这是我的首选选项,但为什么要先添加所有更改?据我所知,这只是修改了 Git 文件中的目录列表,而使用 git reset --hard 时,无论如何这都会丢失,而目录仍将被删除。

我不在 mac 或 linux 上,github windows powershell 有时会在重置后将文件留在那里。我认为这是因为 git reset 将 repo 中的所有文件设置为原始状态。如果它们没有被添加,它们就不会被触及。桌面客户端然后将拾取“嘿,这个文件在这里,需要提交”

有道理。我不使用 Windows,所以没有看到这个问题(至少在过去的几个月里没有使用 Windows,在那之前不记得太多了——这是一个巨大的令人遗憾的模糊)。可能值得注意您的主要答案中的基本原理:)

我现在也在 Mac 上遇到了这个问题。如果文件未在 Repo 中跟踪,有时 git reset 不会触及它。我不能真正隔离“为什么”但是当发生这种情况时,如果我重置,并且我仍然有 1 个或两个未提交的文件,我添加 --all 并再次重置 --hard

我喜欢的一个很好的小变化是 git reset --hard @{u} 它将分支重置到当前远程跟踪分支所在的位置

a
artur

尝试了上述所有解决方案,但仍然无法摆脱新的未暂存文件。

使用 git clean -f 删除这些新文件 - 不过要小心!请注意 force 选项。

s
siddhantsomani

要进行永久丢弃:git reset --hard

保存更改以备后用:git stash

B
Ben Wilde

只需使用:

git stash -u

完毕。简单的。

如果您真的关心您的存储堆栈,那么您可以使用 git stash drop。但那时你最好使用(来自 Mariusz Nowak):

git checkout -- .
git clean -df

尽管如此,我最喜欢git stash -u,因为它仅在一个命令中“丢弃”所有已跟踪和未跟踪的更改。然而,git checkout -- . 只丢弃跟踪的更改,而 git clean -df 只丢弃未跟踪的更改......并且输入这两个命令 太多工作:)

注意:git stash -u 将很快(Git 2.14.x/2.15,Q3 2017)发展一点:stackoverflow.com/a/46027357/6309

如果我得到正确的 OP 问题,则应保留索引文件。只应删除未暂存的更改。在我看来,git stash -k 也是如此。

D
DrB

简单地说

git stash

它将删除您的所有本地更改。你也可以通过说稍后使用

git stash apply 

或 git stash pop

K
Khem Raj Regmi

你有一个非常简单的 git 命令 git checkout .

G
GlassGhost

这甚至适用于以下目录;在正常的 git 权限之外。

sudo chmod -R 664 ./* && git checkout -- . && git clean -dfx

最近发生在我身上

但请注意,git 忽略的内容不会保留其原始权限!因此,它可能会导致安全风险。

@twicejr 你错了,请阅读git help clean“-d 除了未跟踪的文件之外,删除未跟踪的目录。”

你为什么将所有文件设置为世界读/写?不好的做法。

将所有权限设置为 664 对项目需要什么样的权限做出了很多假设。我认为使用该命令的那一部分会给某些人带来问题。

j
jdgregson

无论您的仓库处于何种状态,您都可以随时重置为任何先前的提交:

git reset --hard <commit hash>

这将丢弃该提交后所做的所有更改。

这也将丢弃索引中的所有内容(不仅仅是索引中没有的内容),这超出了 OP 的要求。

v
vivekporwal04
cd path_to_project_folder  # take you to your project folder/working directory 
git checkout .             # removes all unstaged changes in working directory
L
Lahiru Jayaratne

在我看来,

git clean -df

应该做的伎俩。根据Git documentation on git clean

git-clean - 从工作树中删除未跟踪的文件

描述

从当前目录开始,通过递归删除不受版本控制的文件来清理工作树。通常,只删除 Git 未知的文件,但如果指定了 -x 选项,也会删除忽略的文件。例如,这对于删除所有构建产品很有用。如果给出任何可选的 ... 参数,则只有那些路径受到影响。

选项

-d 除了未跟踪的文件之外,还删除未跟踪的目录。如果未跟踪的目录由不同的 Git 存储库管理,则默认情况下不会将其删除。如果您真的想删除这样的目录,请使用两次 -f 选项。 -f --force 如果 Git 配置变量 clean.requireForce 没有设置为 false,除非给定 -f、-n 或 -i,否则 git clean 将拒绝运行。

t
tjb

摆脱比 git clean -df 更具体的新文件的另一种方法(它可以让您摆脱一些文件不一定全部),是首先将新文件添加到索引中,然后存储,然后删除藏。

当由于某种原因无法通过某种普通机制(如 rm)轻松删除所有未跟踪的文件时,此技术很有用。

b
bbarker

如果您正在使用您定期与另一个存储库同步(例如拉取请求)的存储库的分支,那么接下来的内容实际上只是一个解决方案。简短回答:删除 fork 和 refork,但请阅读 github 上的警告。

我有一个类似的问题,也许不完全相同,我很遗憾地说我的解决方案并不理想,但它最终是有效的。

我经常会有这样的 git 状态消息(涉及至少 2/4 个文件):

$ git status
# Not currently on any branch.
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   doc/PROJECT/MEDIUM/ATS-constraint/constraint_s2var.dats
#       modified:   doc/PROJECT/MEDIUM/ATS-constraint/parsing/parsing_s2var.dats
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   doc/PROJECT/MEDIUM/ATS-constraint/constraint_s2Var.dats
#       modified:   doc/PROJECT/MEDIUM/ATS-constraint/parsing/parsing_s2Var.dats

敏锐的眼光会注意到这些文件有一个单独的字母以防万一。不知何故,我不知道是什么导致我走上这条道路(因为我自己没有从上游仓库处理这些文件),我已经切换了这些文件。尝试此页面(和其他页面)上列出的许多解决方案似乎没有帮助。

我能够通过删除我的分叉存储库和所有本地存储库并重新分叉来解决问题。仅此还不够;上游必须将相关文件重命名为新文件名。只要您没有任何未提交的工作、没有 wiki 以及与上游存储库不同的问题,您应该没问题。至少可以说,上游可能对您不太满意。至于我的问题,这无疑是一个用户错误,因为我对 git 不是很精通,但它远非容易修复的事实也表明 git 存在问题。

V
Vadim Kotov

我有一个奇怪的情况,文件总是未暂存,这有助于我解决。

git rm .gitattributes git add -A git reset --hard

t
twicejr

当您想将存储转移给其他人时:

# add files
git add .  
# diff all the changes to a file
git diff --staged > ~/mijn-fix.diff
# remove local changes 
git reset && git checkout .
# (later you can re-apply the diff:)
git apply ~/mijn-fix.diff

[编辑] 如评论所述,可以命名 stash。好吧,如果您想分享您的藏匿处,请使用它;)

实际上 Git stash 可以有一个标题。例如 git stash save "Feature X work in progress"

P
Pau

您可以创建自己的别名,以描述性方式描述如何执行此操作。

我使用下一个别名来丢弃更改。

丢弃工作树中文件(列表)中的更改

discard = checkout --

然后您可以将其用作 next 来丢弃所有更改:

discard .

或者只是一个文件:

discard filename

否则,如果您想丢弃所有更改以及未跟踪的文件,我会混合使用 checkout 和 clean:

清理并丢弃工作树中的更改和未跟踪的文件

cleanout = !git clean -df && git checkout -- .

所以使用很简单,如下所示:

cleanout

现在可以在下一个 Github 存储库中使用,其中包含很多别名:

https://github.com/GitAlias/gitalias