我不小心跑了git reset HEAD
撤消我运行的git reset HEAD~1
没有恢复文件,所以我运行Unstaged changes after reset:
M test/.suman/logs/runner-debug.log
M test/.suman/logs/test-debug.log
M test/.suman/logs/test-output.log
M test/.suman/logs/tests/test.test-src.alphabet.test.js.log
M test/.suman/logs/tests/test.test-src.four.test.js.log
M test/.suman/logs/tests/test.test-src.one.test.js.log
M test/.suman/logs/tests/test.test-src.three.test.js.log
M test/.suman/logs/tests/test.test-src.two.test.js.log
M test/example.js
D test/test-src/one.test.js
D test/test-src/test-sort.js
M test/test-src/z.test.js
似乎没有恢复文件(这应该很容易......)< / p>
现在我明白了:
D test/test-src/one.test.js
我要做的是恢复
this.state
我该怎么做?
答案 0 :(得分:2)
首先运行git reset HEAD
是正确的。这将文件从删除中取消标记,之后将其视为工作目录中的更改。
运行git status
:
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
要恢复文件,即丢弃要删除的文件内容的更改:
$ git checkout -- test/test-src/one.test.js
答案 1 :(得分:1)
mkrieger1's answer是正确的(并且被赞成),但你现在有一个情况,所以需要更多 - 可能是git reset @{1}
- 首先。这是解释。
当您运行git rm path
时,Git从索引(您现在正在构建的下一个提交)中删除了给定的 path
工作树。
当你随后运行git reset HEAD
时,Git做了两次更改,第一次是无操作。但是你运行了一个第二个 git reset
,它也进行了两次更改,这次第一次更改是而不是一个无操作。
git reset
默认执行的操作无论当前分支是什么,它的提交都会更改为HEAD
提交。也就是说,如果您在分支master
上,Git会通过读取HEAD
将master
解析为某个提交ID,然后将刚刚生成的提交ID写入master
。显然,读取ID,然后将其保持不变,保持不变。所以这有点愚蠢,但是这样做是因为如果你说git reset HEAD~1
,例如,Git会将HEAD~1
转换为提交ID,然后将 提交ID写入{{ 1}} - 这是它为第二个命令所做的。
调整当前分支后,master
现在解析为新的提交ID。因此,对于您的第一个HEAD
命令,reset
根本没有更改,而对于您的第二个命令,HEAD
退回一个提交。
然后,由于您让HEAD
执行git reset
(默认)重置,Git会将调整后的--mixed
中的所有文件复制到索引中。
当您撤消HEAD
时,第二步是您想要的一部分。您的git rm
已从工作树中的索引和中删除了该文件。您的git rm
将文件放回索引中,首先在此过程中将git reset HEAD
“更改为”自身。但是你的工作树中仍然缺少该文件 - 然后你做了第二个HEAD
,这使事情变得糟糕,
这是一个粗略的文字图,显示你在两个git reset
之前的内容,就提交图而言,假设你在分支git reset
上:
master
第一个...--A--B--C <-- master
移动git reset
指向提交master
。它已经指出C
所以没有变化。但是, second C
移动git reset
指向提交master
,留下B
悬空:
C
要获得...--A--B <-- master
\
C
,如果您知道其提交ID,则运行:
C
这会告诉Git将当前分支(git reset <commit-id>
)指向再次提交master
:
C
棘手的部分是:在哪里可以找到提交...--A--B
\
C <-- master
的ID?答案是使用 reflogs 。 C
有一个reflog,每个分支有一个reflog。 HEAD
的每一个都会在每次执行更改提交HEAD
的内容时获取一个新条目,并且每次更改分支名称指向的提交时,分支的一个都会获得一个新条目至。由于HEAD
会调整两者,因此可以在两个reflog中找到它们,可能是git reset
和HEAD@{1}
。 (如果你已经做了一些额外的@{1}
s,你可能需要reset
或更高。另外,确保你的shell不吃大括号 - 有些人会这样做;如果你做了,你可能需要使用,例如,@{2}
。)
因此:
"@{1}"
或者可能是一些更高的数字,也许还有一些额外的引号。这应该让你的分支指向正确的提交,和填写索引。 (或者,您可以使用原始哈希ID,如果有的话.Git可以使用哈希ID,也可以使用任何将转换为哈希ID的内容。要查看某些哈希ID转换为什么,请使用{{ 1}}。例如,尝试git reset @{1}
和git rev-parse
。)
现在您已将分支指向正确的提交 - 即现在您回到:
git rev-parse HEAD
或类似 - 执行git rev-parse master
重置的...--A--B--C <-- master
仍会将所需文件保存在索引中,但不会保存在 work-tree <中/ em>的
有几种方法可以恢复文件,但最简单的方法是将其从索引复制到工作树:
git reset
即使您根本没有运行任何 --mixed
命令,也可以使用它:
git checkout -- path
关键区别在于此版本说:将{{1>}提交中的给定 git reset
复制到索引中,然后复制它 git checkout HEAD -- path
从索引到工作树。