git reset --hard和git clean的区别

31

你好,我对这两个命令的区别很感兴趣。当他们在这里介绍时:https://www.atlassian.com/git/tutorials/undoing-changes

看起来 git reset --hard 命令也会将暂存区和工作目录设置为与最新提交相匹配,但最后他们说 git reset --hard 不会改变当前的工作目录。因此,我在这里非常困惑,请有人澄清一下吗?


1
它在哪里说“git reset --hard不会改变当前工作目录”?它明确表示相反的意思 - “换句话说:这个[硬重置]会消除所有未提交的更改”。 - user2864740
1
此外,请注意:“请记住,[硬]重置仅影响已跟踪的文件,因此需要单独使用[clean]命令来清理未跟踪的文件。” - user2864740
@user2864740,它会清除所有未提交的更改,但如果它还重置工作目录以匹配最后一次提交,那么为什么我们仍然需要git clean命令呢?因为在这种情况下,由于工作目录和暂存区相同,所以不会有任何未跟踪的文件。 - AlexWang
2
请注意,您工作目录中的每个文件都可以处于两种状态之一:已跟踪或未跟踪。已跟踪的文件是上一个快照中的文件;它们可以是未修改的、已修改的(表示未暂存/未提交的更改)或已暂存的(表示未提交的更改)。未跟踪的文件是其他所有文件 - 您工作目录中的任何文件都不在您的最后一个快照中,也不在您的暂存区中(未跟踪)。 - user2864740
1
也许这是一项非常繁琐的、改变生活的、至关重要的、不可复制的艺术工作,但却被遗忘了添加到git中。在这种情况下,我会说它很重要/有用——如果它被运行git clean删除了,那可能会让人心烦意乱。我听到的最大的抱怨之一是新用户忘记添加[并随后进行]文件的阶段。Git不会丢失更改[没有一点帮助]-但有些更改根本就没有进入git! - user2864740
显示剩余2条评论
1个回答

22
他们有两个不同的功能。比如说,你执行了GIT PULL,然后开始编辑一些文件,可能已经添加并提交了这些更改以进行推送...但是由于某种原因,你决定放弃对给定文件所做的所有更改,并返回到较早的状态。在这种情况下,你需要执行:
$ git reflog
... snip ...
cf42fa2... HEAD@{0}: commit: fixed misc bugs
~
~
cf42fa2... HEAD@{84}: commit: fixed params for .....
73b9363... HEAD@{85}: commit: Don't symlink to themes on deployment.
547cc1b... HEAD@{86}: commit: Deploy to effectif.com web server.
1dc3298... HEAD@{87}: commit: Updated the theme.
18c3f51... HEAD@{88}: commit: Verify with Google webmaster tools.
26fbb9c... HEAD@{89}: checkout: moving to effectif

选择您想要回滚到的提交,如下所示:

git reset --hard 73b9363

重置 HEAD 后,所有更改/暂存的文件都将消失。

至于 git clean。以下是 git-scm.com 对其的描述。

DESCRIPTION
Cleans the working tree by recursively removing files that 
are not under version control, starting from the current directory.

Normally, only files unknown to Git are removed, but if the -x
option is specified, ignored files are also removed. This 
can, for example, be useful to remove all build products.

If any optional <path>... arguments are given, only those paths are affected.

有关重置和清除及其--选项的更多内容

lnydex99uhc:~  user$ git reset -h
usage: git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]
   or: git reset [-q] <tree-ish> [--] <paths>...
   or: git reset --patch [<tree-ish>] [--] [<paths>...]

    -q, --quiet           be quiet, only report errors
    --mixed               reset HEAD and index
    --soft                reset only HEAD
    --hard                reset HEAD, index and working tree
    --merge               reset HEAD, index and working tree
    --keep                reset HEAD but keep local changes
    -p, --patch           select hunks interactively

VS

 lnydex99uhc:~ user$ git clean -h
    usage: git clean [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>...

        -q, --quiet           do not print names of files removed
        -n, --dry-run         dry run
        -f, --force           force
        -i, --interactive     interactive cleaning
        -d                    remove whole directories
        -e, --exclude <pattern>
                              add <pattern> to ignore rules
        -x                    remove ignored files, too
        -X                    remove only ignored files

谢谢分享。这是否意味着这是一个强有力的命令,可能会影响项目未来的编码? - AlexWang
这将影响最近的更改,通过重置到早期提交,您告诉git删除自上次提交以来的所有新更改。 - z atef
关于“所有更改/暂存文件都将消失”的问题 - 这只会影响未提交的更改。已提交的更改(如reflog所示)将始终被保留,并且只要它们可达 - 例如,通过分支、标签或子系统,就可以随时恢复它们。(Git“丢失”提交的唯一时间是在GC运行并且它们是可达的情况下,除非通过ID访问。)改写提交是一个不同的问题,但是git reset无法修改/删除先前的提交。 - user2864740
只要没有修改/暂存文件并且所有更改都已提交或藏起来,那么git reset实际上并不会“影响[现有的或]未来的编码”,因为回滚也很容易。失去未提交的更改是一个即时的问题,而不是一个长期的问题。 - user2864740

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