如何丢弃Git中未进行的变更?


4815

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


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

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

15
'git clean -df'被警告!我试过了,丢失了无法还原的密钥文件夹...糟糕!
·卡卡尼斯

46
点击git status就可以做到这一点! git checkout -- .
Paulo

4
@Paulo:在2019年7月开始,git status给出了建议:git restoregit restore是专门用于此目的的新命令。请参阅我的2019年更新
prosoitos

Answers:


2684

另一种更快的方法是:

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

--include-untracked如果您不希望它做得太透彻,则无需包括在内。

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


121
而且要彻底,您也想要--include-untracked
TJ Crowder 2015年

9
@KarimSamir:该问题专门询问不在索引中的更改。该git reset命令也将丢弃索引中的更改。
格雷格·休吉尔

146
git checkout- 快得多
Frank

38
无论是git stash,也没有任何各种git checkout将丢弃不分级删除。根据输出git status,这里的实际正确答案是某种味道git reset HEAD
克里斯·沃思

127
这会污染存储堆栈。git checkout -- .仅使用一个命令执行该作业。
费利佩·托内罗

5332

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

git checkout -- .

对于特定文件,请使用:

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

--这里消除争论的歧义


117
这似乎是git的规范方法。即确切地告诉您,如果您键入git会做什么git status
ABMagil 2014年

27
如果存在未跟踪的文件,则不起作用。吉特说error: The following untracked working tree files would be overwritten by checkout: ...
Michael Iles 2014年

92
新手问题,“ git checkout-”是什么?在语义上是指?
kaid 2014年

120
@Ninjack与的git checkout -- .含义相同git checkout .,不同之处在于您明确表示未指定分支名称。他们俩都说我在当前所在的分支上签出HEAD版本。要么 '。/'。如果您通常这样做git checkout branch-name directory-or-file-name,则会获得directory-or-file-nameon branch 的HEAD版本branch-name
akgill 2014年

23
IMO这个变体是不完美的,因为当更改清除时更改的存储库不在HEAD修订版上并且您不想将其更新为HEAD且仅希望清除更改时,它无法处理这种情况。
alexykot 2015年

1897

似乎完整的解决方案是:

git clean -df
git checkout -- .

git clean删除所有未跟踪的文件(警告:虽然它不会删除.gitignore中直接提及的被忽略文件,但可能会删除驻留在文件夹中的被忽略文件),并git checkout清除所有未暂存的更改。


116
其他两个答案实际上并不起作用,而这个答案确实有效。
约翰·亨特2014年

18
@dval,这是因为第一个命令删除了未索引文件,第二个命令删除了未暂存的更改(索引文件)。因此,如果您没有任何阶段性的更改,则此操作与还原为上一次提交的操作相同git reset --hard
Amanuel Nega 2014年

3
如果未跟踪的目录是git clone,请使用-dff
accuya 2014年

87
小心运行git clean -df。如果你不明白它做什么,你可能会被删除的文件你的意思是保持一样的robots.txt,上传文件等
ctlockey

40
作为@ctlockey说,第一个命令还删除目录,如果它们是由被忽略的文件的唯一 ......忘记了一大堆的配置文件在我的项目:(小心。
马克西姆洛伦特

326

这会签出当前目录的当前索引,从而丢弃文件从当前目录向下的所有更改。

git checkout .

或此操作从索引中检出所有文件,覆盖工作树文件。

git checkout-index -a -f

28
嗨,git checkout .和之间有什么区别git checkout -- .
Evan Hu

5
@Evan:在这种情况下没有区别。
罗伯特·西默

10
@Robert Siemer,一般情况下?
RJFalconer 2015年

2
@Evan:问这个问题的好地方。–它与OP的问题无关,也与此处的答案无关。
罗伯特·西默

14
+1这是正确的答案,因为它可以正确处理某些文件已暂存未暂存更改的情况。请注意,此解决方案可以取消未分段的更改;如果您希望保留它们,则应使用@ greg-hewgill的答案git stash save --keep-index
Rhubbarb 2015年

248
git clean -df

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

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

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

运行git help clean以查看手册


为什么这个答案没有所有选票?答案在2011年仍然正确。
尤金·布拉吉内斯

106

我最喜欢的是

git checkout -p

这样就可以有选择地还原块。

也可以看看:

git add -p

9
我喜欢能够在放弃之前看到实际更改的功能。
Penghe Geng 2015年

这就是我用的。git checkout -p,然后“ a”接受所有内容。
马蒂斯(Matis)

2
我没想过 这-p增加了额外的安全性。结合使用git clean -d以实际回答OP。
Stephan Henningsen

96

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

git clean -dfx
git checkout .

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

-d

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

-f

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

-x

不要使用.gitignore(按目录)和中$GIT_DIR/info/exclude的忽略规则,但仍要使用-e选项提供的忽略规则。这允许删除所有未跟踪的文件,包括构建产品。可以使用它(可能与结合使用git reset)创建原始工作目录以测试干净的构建。

另外,git checkout .需要在回购的根目录中完成。


此解决方案+1。关于您所说的“需要在仓库的根目录进行git checkout”,您也许会提到我们可以git reset --hard代替它?(实际上等价于git reset --hard HEAD当前目录,并且应该能在其中运行)
ErikMD '18

2
同样关于第一个命令git clean -dfx,这里有个提示,我在运行它之前会很安全:刚运行git clean -d -x -n之前,显示要删除的文件列表,然后通过运行确认操作git clean -d -x -f(我把参数-n-f最终可以在终端中对其进行快速更改)
ErikMD,

5
快速说明,这是不可逆的,如果您有文件,.gitignore将会丢失它们。因此,在此之前请考虑备份您的项目。
罗布

69

如果您只想删除对现有文件的更改,请使用checkout在此处记录)。

git checkout -- .
  • 没有指定分支,因此它签出当前分支。
  • 双连字符(--)告诉Git,以下内容应作为其第二个参数(路径),而忽略了分支的指定。
  • 句点(.)表示所有路径。

如果要删除自上次提交以来添加的文件,请使用clean在此处记录):

git clean -i 
  • -i选项启动一个交互式clean,以防止误删除。
  • 还有一些其他选项可用于更快地执行。请参阅文档。

如果您希望将更改移至存放空间以供以后访问,请使用stash在此处记录):

git stash
  • 所有更改都将移至Git的存储库,以便以后访问。
  • 少数选项可用于更细微的隐藏;请参阅文档。

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

对此进行了投票:)
Archie

62

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

有几种不同的情况:

  1. 如果尚未暂存文件,则使用git checkout。签出“更新工作树中的文件以匹配索引中的版本”。如果文件尚未暂存(又添加到索引),则此命令实际上会将文件还原为您的最后一次提交。

    git checkout -- foo.txt

  2. 如果已暂存文件,则使用git reset。重置会更改索引以匹配提交。

    git reset -- foo.txt

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

请参阅上面的文章以获取更多建议。


60

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

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

git checkout -- .

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

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

git stash -u

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


19
我两次来到这里,阅读了这个答案,.最后忘记了。为了我未来:这段时间至关重要
bejado

2
我需要摆脱子目录中的所有本地更改,而又不浪费其他所有更改。这个答案很有帮助,谢谢
Ally

2
请描述这两个命令的作用。没有解释真的没有帮助。
克里斯·肯尼迪

2
优秀的。结帐在一项命令中完成,而最受欢迎的一项在两项中完成。还可以跟进git clean -fd以清理不在索引中的文件。
oligofren

49

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

git diff | git apply --reverse

44

git checkout -f


man git-checkout

-f, --force

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

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


2
这将丢弃索引中的更改!!(并且OP要求保留它们原样。)
Robert Siemer

44

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

例如 git checkout -- .


1
投票不足,因为它无助于快速丢弃所有文件。三个点表示您需要列出所有文件。例如,如果您需要一次丢弃大量文件,则这特别糟糕。一个大的合并过程中,你已经上演了所有的修改后,你喜欢让
USR-本地ΕΨΗΕΛΩΝ

2
当然,正确的命令是“ git checkout-”。一个点。在评论中,三个点是一个语法的事情,表示有可能已被用于许多其他的选择..
Josef.B

39

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

git add .
git stash

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

git stash drop

比拉勒·马格索德(Bilal Maqsood)的答案git clean也对我有用,但是有了藏身处,我有了更多的控制权-如果我不小心做某事,我仍然可以找回我的更改

更新

我认为还有1种更改(以前不知道为什么对我有用):

git add . -A 代替 git add .

没有已-A删除文件的文件将不会上演


38

2019更新:

20197月以来,已经有一个新的命令执行此操作:git restore

在中git status,现在Git建议使用此命令而不是git checkout以前的命令。

尽管此命令还可用于将工作树还原到特定的提交或还原索引的内容,但默认情况下,工作树将还原到索引中的状态(此处要求)。

因此,为了还原与pathspec匹配的文件(摆脱它们未进行的暂存更改),您可以执行以下操作:

git restore <pathspec>

例如,要恢复当前目录中所有未暂存的更改,可以运行:

git restore .

如果从项目的根目录运行此命令,它将恢复整个存储库中所有未分段的更改。

请注意,与git checkout -- .(如Mariusz Nowak所指出的)一样,这将仅丢弃对Git跟踪的文件的更改,而不会丢弃任何新的未跟踪的文件。如果要丢弃任何未暂存的更改,包括新的未跟踪文件,则可以运行其他:

git clean -df

但是,请谨慎使用此后面的命令,因为您可能会丢弃不想删除的文件。


注意git restore:由于这是一个新命令,因此其手册页会发出警告:

此命令是实验性的。行为可能会改变。

因此,如果将来的行为发生变化,则此答案可能会过时。因此,man git-restore在使用前先快速运行可能是明智的。


2
我只想还原我的暂存更改,而又不影响新添加的文件,因此 git restore .效果很好。谢谢。
萨拉·米斯拉

3
我做到了git restore <filename>,而且效果很好。
Merlin

1
对我来说很好。
普罗米修斯

1
根据手册页,git restore .将所有文件还原到当前目录中,而不是整个存储库中。
佳诺

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

35

我没有放弃更改,而是将遥控器重置为原始位置。注意-此方法是将文件夹完全还原到仓库中的文件夹。

因此,我这样做是为了确保当我重新设置git时,他们不会坐在那儿(以后-不包括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时,无论如何,这仍然会丢失,而目录仍会被删除。
XtrmJosh 2015年

我不在Mac或Linux上,github Windows powershell有时在重置后会将文件留在那里。我认为是因为git reset将回购中的所有文件都设置为原始状态。如果未添加,则不会被触摸。然后,桌面客户端将提取“嘿,此文件位于此处,需要提交”
Nick

有理有据。我不使用Windows,所以从未见过该问题(至少最近几个月没有使用Windows,在此之前不记得太多-这是一个令人遗憾的巨大模糊)。可能值得注意您的主要回答的理由:)
XtrmJosh

我现在也在Mac上遇到了这个问题。如果在仓库中没有跟踪文件,有时git reset不会碰到它。我无法真正隔离“为什么”,但是当发生这种情况时,如果我重新设置,但我仍然有1个或两个未提交的文件,我会添加--all并重新设置--hard
Nick

2
我喜欢的一个不错的小变化是git reset --hard @{u}将分支重置为当前远程跟踪分支所在的位置
user2221343

31

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

使用git clean -f删除那些新文件- 但是要小心!注意强制选项。


21

简单地说

git stash

它将删除所有本地更改。您还可以稍后说

git stash apply 

或git stash pop


21

只需使用:

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
VonC

如果我得到正确的OP问题,应保留索引文件。仅应删除不定期的更改。git stash -k我认为应该是这样。
快照

21

要永久丢弃: git reset --hard

要保存更改以供以后使用: git stash


16

即使在以下目录中也可以使用:超出正常的git权限。

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

最近发生在我身上


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

@twicejr您输入的是错误的,请阅读git help clean“ -d除未跟踪的文件外,删除未跟踪的目录”。
GlassGhost 2014年

为什么将所有文件都设置为全局可读写?不好的做法。
Ghoti

@Ghoti我不好,664对吗?也欢迎您编辑答案。
GlassGhost

将所有权限设置为664会对项目需要哪种权限做出很多假设。我认为使用命令的这一部分会对某些人造成问题。
ianrandmckenzie


14
cd path_to_project_folder  # take you to your project folder/working directory 
git checkout .             # removes all unstaged changes in working directory

12

在我看来,

git clean -df

应该可以。根据git clean上的Git文档

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

描述

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

通常,仅删除Git未知的文件,但是如果指定-x选项,也会删除忽略的文件。例如,这对于删除所有构建产品很有用。

如果给出任何可选的...参数,则仅影响那些路径。

选件

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

-f --force如果Git配置变量clean.requireForce未设置为false,除非给定-f,-n或-i,否则git clean将拒绝运行。


11

无论您的存储库处于什么状态,都可以始终重置为以前的任何提交:

git reset --hard <commit hash>

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


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

10

删除比git clean -df更具体的新文件的另一种方法(它将允许您删除某些文件(不一定是全部文件)),是先将新文件添加到索引,然后隐藏,然后删除藏。

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


9

如果您使用的是存储库的派生库,并且在其中定期与另一个存储库定期进行同步(例如拉取请求),那么以下内容实际上只是一个解决方案。简短答案:删除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

敏锐的眼睛会注意到,这些文件中的dopplegangers都是单个字母,以防万一。不知何故,我不知道是什么让我沿着这条路开始的(由于我自己不是从上游仓库使用这些文件),所以我已经切换了这些文件。尝试此页面(和其他页面)上列出的许多解决方案似乎无济于事。

我可以通过删除叉状存储库和所有本地存储库并重新分叉来解决此问题。仅此一项是不够的。上游不得不将有问题的文件重命名为新文件名。只要您没有任何未提交的工作,没有Wiki和没有与上游存储库不同的问题,就可以了。至少可以说,上游可能对您不太满意。至于我的问题,毫无疑问,这是一个用户错误,因为我对git并不熟练,但是事实也很不容易解决git问题。


7

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

# 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

[编辑]如所评论,可以命名藏匿处。好吧,如果您想共享存储空间,请使用它;)


5
实际上,Git隐藏可以有一个标题。例如git stash save "Feature X work in progress"
Colin D Bennett

7

您可以创建自己的别名,该别名以描述性方式描述如何进行。

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


放弃工作树中文件列表的更改

discard = checkout --

然后,您可以将其用作下一步以放弃所有更改:

discard .

或只是一个文件:

discard filename

否则,如果您要舍弃所有更改以及未跟踪的文件,那么我将使用checkout和clean:

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

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

因此,使用非常简单,如下所示:

cleanout

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


7

我遇到了一个奇怪的情况,即文件始终处于未暂存状态,这可以帮助我解决。

git rm .git属性
git add -A
git reset --hard

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.