Pro Git解释git reset
就像这样:
小结
reset
命令按特定顺序覆盖这三棵树,当你告诉它时停止:
- 将分支HEAD点移至(如果
--soft
,则停在此处- 使索引看起来像HEAD (在此处停止,除非
--hard
)- 使工作目录看起来像索引
醇>
我理解的方式是,如果我git reset --hard
,那么我的索引和工作目录都会像我的HEAD一样完全。所以我继续这样做了:
# 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 + staged 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
)进行了类似的测试,我得到了类似的结果:暂存的文件都消失了,但是git reset --hard
之后仍然存在未分段的文件。
有人可以解释我是否误解了git reset
的任何内容?
答案 0 :(得分:1)
如" Undoing Changes"
中所述
git clean
命令通常与git reset --hard
一起执行 请记住,重置只会影响跟踪的文件,因此需要单独的命令来清除未跟踪的文件。组合使用这两个命令可以将工作目录返回到特定提交的确切状态。
--hard
选项记录为:
重置索引和工作树 自
<commit>
以来对工作树中跟踪的文件的任何更改都将被丢弃。
这在2008年已经讨论过了 Simply put by Linux Torvalds:
如果你习惯做&#34;
git checkout -f
&#34;或者&#34;git reset --hard
&#34;,这两个检查(*)都被忽略了。毕竟,你要求强制切换。
(*检查=脏文件或未跟踪文件)
至少在第二种情况下,我认为发生的是git赢了 删除它不知道的文件,这样你就会有一个&#34; turd&#34;离开了。
已添加文件...即使从未提交过(全新),仍然会被git reset --hard
删除为seen also in 2008:
我昨天意外删除了数百个新添加的文件 这样做。
我的问题是为什么&#34;
git reset --hard
&#34;不能成为一个特例 新添加的跟踪文件?
毕竟,&#34;git status
&#34;知道他们已经&#34;新文件&#34;和&#34;git reset --hard
&#34;我们可以意识到,从地球上擦掉它们并不是最有帮助的事情。
作为建议,git read-tree -m HEAD
或git rm --cached <file list>
之前 git reset --hard
有助于保留这些新文件(将其从索引中移除)
你会想要&#34;
reset --hard
&#34;当在HEAD中不存在路径但在其他情况下在索引中时删除该路径 而且,根据我的经验,这往往是最理想的。
(就像摆脱冲突的合并一样)
请注意,在此实例中,git fsck
can still help recover those deleted new files。
答案 1 :(得分:1)
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将删除哪些文件。这样可以轻松避免出现问题。