难以使工作树看起来像索引?
Pro Git解释如下的git reset
:
概括
reset
命令按照特定的顺序覆盖这三棵树,当你告诉它时:
--soft
,则停在此处) --hard
) 我理解的方式是,如果我git reset --hard
,那么我的两个指标,我的工作目录将成为完全像我的头。 所以我继续做下去:
# make a git repo
mkdir mygitrepo
cd mygitrepo
git init
# init commit
touch old_file
git commit -a
# stage a file
touch staged
git add staged
# create file that is not staged
touch unstaged
到目前为止,我的回购看起来像这样:
HEAD
old_file index
old_file +上演 working dir
old_file + staged + unstaged 现在,如果我运行git reset --hard
那么我希望我的回购变成:
HEAD
old_file index
old_file working dir
old_file 但我会得到这个:
HEAD
old_file index
old_file working dir
old_file + unstaged 我通过显式传递目标参数来做类似的测试,比如git reset --hard target
,而且我得到了类似的结果:staged文件全部没了,但未归档的文件在git reset --hard
后仍然存在。
有人可以解释我是否误解了有关git reset
任何内容?
正如“撤销更改”中所述
git clean
命令通常与git reset --hard
一起执行。
请记住,重置仅影响跟踪的文件,因此需要单独的命令清理未跟踪的文件 。
结合起来,这两个命令可让您将工作目录返回到特定提交的确切状态。
--hard
选项记录为:
重置索引和工作树。
放弃自<commit>
以来对工作树中跟踪文件所做的任何更改。
早在2008年就已经讨论过了。
Linux Torvalds简单地说:
如果你习惯做“ git checkout -f
”或“ git reset --hard
”,那么这两个检查(*)都会被忽略。 毕竟,你要求强制切换。
(*检查=脏文件或未跟踪文件)
至少在第二种情况下, 我认为会发生的事情是git不会删除它不知道的文件,所以你会留下一个“烂”字 。
虽然增加了文件,即使从未提交过(即全新的),仍然会被git reset --hard
删除,如2008年所见:
我实际上意外删除了数百个新添加的文件,昨天就这样做了。
我的问题是为什么“ git reset --hard
”不能为新添加的跟踪文件制作特殊情况?
毕竟,“ git status
”知道它们是“新文件”,而“ git reset --hard
”可以意识到,将它们从地球表面抹去并不是最有用的可能。
作为一个建议,在git reset --hard
前git read-tree -m HEAD
或git rm --cached <file list>
git reset --hard
会帮助保留这些新文件(将它们从索引中删除)
Junio C. Hamano stil认为:
当HEAD中不存在路径但在其他情况下在索引中存在路径时,您会想要“ reset --hard
”来移除该路径 。
这是我的经验,往往不是它是可取的。
(比如摆脱冲突合并中的残酷)
请注意,在这种情况下, git fsck
仍然可以帮助恢复这些被删除的新文件。
Git总会遵循一条重要规则(除非明确告知不要这样做): 不要触摸未跟踪的文件 。
使用默认功能,Git不会执行任何会导致未跟踪文件数据丢失的操作。 这是因为来自未跟踪文件的信息永远无法通过Git恢复:它不会“知道”它们,因此它不会将其内容存储到任何地方,因此对它们进行任何操作都非常危险。 所以它不会触及它们。
这也是为什么如果分支包含具有相同路径的跟踪文件,Git不会让您切换到未跟踪文件的分支。 因为这样做会覆盖未跟踪的文件,将其替换为来自该分支的文件,但无法恢复未跟踪的文件。 因此,Git将不会切换分支,要求您首先处理未跟踪的文件(这可能意味着将其重命名,将其添加到Git中,甚至删除它)。
所以当你做git reset
,你只会影响索引。 而git reset --hard
会影响索引和工作目录。 而对于Git,工作目录只包含跟踪的文件。 这就是为什么git reset --hard
既不会删除未记录的文件,也不会删除位于.gitignore
文件。 Git不会“知道”它们,所以它不会触及它们。
如果你想删除未跟踪的文件,有一个命令负责:git clean。 该命令附带了不同的参数组合,它们都执行各种不同的作业。
默认情况下, git clean -f
会删除未跟踪的文件,但保留忽略的文件。 如果你还想删除被忽略的文件,你可以使用git clean -x -f
。 请注意,您通常必须始终指定-f
(或--force
)作为git clean
来执行任何操作。 这只是一个额外的安全机制,以确保你知道你在做什么。 您可以使用-n
来执行干运行,并只显示Git将删除的文件。 这可以很容易地避免问题。