0

我不小心跑了git rm file

撤消我运行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

我想做的是恢复

 D       test/test-src/one.test.js

我怎样才能做到这一点?

4

2 回答 2

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
于 2017-01-13T22:43:43.240 回答
1

mkrieger1 的答案是正确的(并且被赞成),但是你现在有一个情况,所以需要更多——可能是——git reset @{1}首先。这是解释。

当您运行时,Git从索引(您现在正在构建的下一个提交)和工作树中删除了给定的内容。git rm pathpath

当您随后运行git reset HEAD时,Git 进行了两项更改,其中第一项是空操作。但是随后您运行了第二个 git reset也进行了两个更改,而这一次第一个更改不是空操作。

git reset默认情况下做什么

  • 无论当前分支是什么,它的提交都会更改为HEAD提交。也就是说,如果你在 branch 上,Git通过读取master解析到某个提交 ID ,然后将它刚刚生成的提交 ID 写入. 显然,读取 ID,然后将其原封不动地写回,使其保持不变。所以这有点愚蠢,但这样做是因为如果你说,例如,Git 会转换为一个提交 ID,然后将该提交 ID 写入- 这就是它为你的第二个命令所做的。HEADmastermastergit reset HEAD~1HEAD~1master

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

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

当您撤消git rm. 您git rm从索引工作树中删除了该文件。您git reset HEAD将文件放回索引中,首先HEAD在此过程中“更改”为自身。但是您的工作树中仍然缺少该文件-然后您执行了第二个git reset,这使事情变得很糟糕,

恢复大部分_

就提交图而言,这是您在两个 s 之前所拥有的粗略文本git reset图,所有这些都假设您在分支上master

...--A--B--C   <-- master

第一个git reset移动master到指向 commit C。它已经指出,C所以没有改变。但是,第二个 git reset指向mastercommit B,留下C悬空:

...--A--B    <-- master
         \
          C

C返回,如果您知道它的提交 ID,您将运行:

git reset <commit-id>

这将告诉 Git 指向当前分支 ( master) 再次提交C

...--A--B
         \
          C   <-- master

棘手的部分是:在哪里可以找到 commit 的 ID C?答案是使用reflogs。有一个HEADreflog,每个分支都有一个 reflog。HEAD每次您执行更改提交HEAD指向的操作时,for 都会获得一个新条目,而分支名称每次更改分支名称指向的提交时都会获得一个新条目。由于git reset两者都进行了调整,因此它们会在两个 reflogs 中找到,可能是HEAD@{1}@{1}。(如果你做了一些额外reset的 s 你可能需要@{2}或更高。另外,确保你的壳不吃大括号——有些吃;如果你吃,你可能需要使用,例如,"@{1}"。)

因此:

git reset @{1}

或者可能是一些更高的数字,可能还有一些额外的引号。这应该让您的分支指向正确的提交,填写索引。(或者,您可以使用原始哈希 ID,如果有的话。Git 采用哈希 ID 或任何转换​​哈希 ID 的内容。要查看转换为什么哈希 ID,请使用。例如,git rev-parse尝试和。)git rev-parse HEADgit rev-parse master

剩下的路

现在您已经将分支指向了正确的提交——也就是说,现在您回到了:

...--A--B--C   <-- master

或类似的 -git reset进行--mixed重置后,仍将所需文件存储在index中,但不在work-tree中。

有几种方法可以取回文件,但最简单的是将它从索引复制到工作树:

git checkout -- path

即使您根本没有运行任何 git reset命令,您也可以使用它:

git checkout HEAD -- path

关键区别在于这个版本说:将提交中的给定复制pathHEAD索引中,然后将相同path的从索引复制到工作树。

于 2017-01-14T00:04:09.527 回答