运行“git rm”后运行“git reset”后取消删除文件

时间:2017-01-13 22:00:16

标签: git git-reset git-rm

我不小心跑了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

我该怎么做?

2 个答案:

答案 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会通过读取HEADmaster解析为某个提交ID,然后将刚刚生成的提交ID写入master。显然,读取ID,然后将其保持不变,保持不变。所以这有点愚蠢,但是这样做是因为如果你说git reset HEAD~1,例如,Git会将HEAD~1转换为提交ID,然后将 提交ID写入{{ 1}} - 这是它为第二个命令所做的。

    调整当前分支后,master现在解析为新的提交ID。因此,对于您的第一个HEAD命令,reset根本没有更改,而对于您的第二个命令,HEAD退回一个提交。

  • 然后,由于您让HEAD执行git reset(默认)重置,Git会将调整后的--mixed中的所有文件复制到索引中。

    < / LI>

当您撤消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 resetHEAD@{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 从索引到工作树。