我刚刚失去了所有的工作吗?如何恢复我的本地数据? (Git)

Did I just lose all my work? How to restore my local data? (Git)

我对 git 很陌生。我是个白痴,我在使用它时并不知道自己在做什么。不小心用master覆盖了我本地的所有东西。 36e6aed 是我 9 天前在 master 上执行的提交。我可以恢复我的 'major updates' 提交吗?

注意:在此之前我 git 添加了 .然后我在那之后输入了错误的东西,感到困惑,退出了 window,并做了下面打印的事情。

location/of/local/branch (master|MERGING)
$ git stash
Saved working directory and index state WIP on master: 36e6aed Restructure

location/of/local/branch (master)
$ git commit -m 'major updates'
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

location/of/local/branch (master)
$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

location/of/local/branch (master)
$ git reflog
36e6aed (HEAD -> master, origin/master) HEAD@{0}: reset: moving to HEAD
36e6aed (HEAD -> master, origin/master) HEAD@{1}: commit: Restructure
b1ad2dc HEAD@{2}: pull origin master: Merge made by the 'ort' strategy.
5173228 HEAD@{3}: commit: tortoise mods
3df3009 HEAD@{4}: commit: Restructure
76a5c29 HEAD@{5}: pull origin master: Fast-forward
da38dd1 HEAD@{6}: pull: Fast-forward
122b86d HEAD@{7}: pull: Merge made by the 'ort' strategy.
bdc9928 HEAD@{8}: commit: In & Out folders
f339839 HEAD@{9}: commit (initial): Initial Commit

您没有 major updates 提交。幸运的是,您确实 提交了;我们很快就会把它拿回来。当你 尝试 制作那个时,Git 是这样说的:

$ git commit -m 'major updates'
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

这条(不是很有帮助)Git 消息说“我没有做任何事,因为没有事可做。”

这里的诀窍是意识到为什么无事可做,这是从尝试提交之前开始的:

location/of/local/branch (master|MERGING)
$ git stash
Saved working directory and index state WIP on master: 36e6aed Restructure

git stash 命令的意思大致是:提交我现在所拥有的,但是 根本没有 b运行ch,然后删除所有工作,因为它已安全地保存在提交中。 所以您确实进行了提交,但它不在任何 b运行ch 上。要取回它,只需 运行 git stash apply仔细检查结果以确保您喜欢它,然后——当且仅当你喜欢它时——运行 git stash drop.

(你可以运行git stash pop。这意味着应用并立即删除。我建议将步骤,以便您可以先检查。通常情况下,应用很好并且下降是正确的,但这有点像闭上眼睛并从桥上跳下希望您落在湖中而不是湖边的岩石上。)

除此之外还有更多内容,但在您的情况下,您只想取回隐藏的内容,以便您可以正常提交。

更多

你的 shell 提示,在你 运行 git stash 之前,显示:

location/of/local/branch (master|MERGING)

这意味着您正在使用 Git-aware shell 提示包之一。那个特定的包注意到您正处于合并的中间,可能是由于冲突而暂停的合并。当您调用 git merge—并且 git pull 将为您 调用 git merge ,这算作您调用了 git merge—Git 尝试 合并工作 。 Git 并不总是能够自己完成。

当 Git 尝试将您的工作(您在 b运行ch 上的提交)与其他人的工作(他们在 b运行ch[=143 上的提交)结合起来=]1), 这可能会很顺利,也可能不会。如果 顺利进行,Git 将经常2 进行新的提交。但是,如果不是,合并会在中间停止,那些 prompt-setting shell add-ons 插入 |MERGING 符号。

当合并 确实 像这样在中间停止时,Git 会使您的工作树变得一团糟。3 你的工作是解决混乱和 运行 git add。 运行 git add 上的冲突文件告诉 Git 您已正确解决冲突。 Git 假定您知道自己在这里做什么,并且此时将工作树副本中的任何内容作为 正确 分辨率。

当你 运行 git add . 你告诉 Git 扫描整个当前目录和 sub-directories——可能是你的整个工作树——和 git add每个文件。所以这告诉 Git 你解决了 所有 的冲突。在你这样做之前,你不能进行 new 提交,甚至不能进行 git stash 的提交。所以你的 git stash 工作 因为 你 运行 git add ..

如果您真的准备好了(已经解决了所有问题),git stash popgit stash apply您将获得你想要什么。如果不是,您仍然需要 git stash applygit stash pop 步骤,但之后,您需要恢复解决冲突:应用步骤将带回任何未解决的冲突标记部分。 Git 不能在这里帮助你,因为你已经告诉 Git 你解决了 一切 ,所以 Git 忘记了冲突是什么,并且会认为其中包含冲突标记的工作树文件 正确的 分辨率(尽管几乎可以肯定不是)。您只需要仔细检查您计划提交的内容(使用 git diff and/or git diff --staged 找出答案)。


1Git中的b运行ch这个词有很大问题:意思是在至少两三个不同的事物,每次有人说出或读到这个词时,含义都会发生变化。另见 What exactly do we mean by "branch"? 在这种情况下,“your b运行ch”和“their b运行ch”可能具有相同的 name——例如,两者都可能被称为 master——但它们在两个不同的 存储库 中并且实际上是不同的 b运行ches,至少在许多意义上“b运行ch”这个词。这一切都非常令人困惑和不幸。

2git merge 命令有时不需要进行任何实际的合并,除非您强制它这样做,否则不会进行新的提交. Git 将此 not-actually-merging 操作称为 快进合并 ,即使没有实际合并。这也令人困惑和不幸。

3你的工作树work-tree是你做你的工作。 Git合作ies 文件脱离一些提交,使它们成为普通文件;但这些文件实际上并不是Git中。然后您处理/使用这些副本。当您准备好将它们用于新提交时,您 运行 git add 让 Git 扫描更新的文件并准备它们,然后您 运行 git commit 提交扫描结果,这些结果是 Git 的内部形式,而不是您的工作树中的文件。


还有一件事

虽然您可能还没有准备好(并且可以在完成工作时忽略它),但您应该知道 git stash 实际上 至少有两个 承诺。 git stash 进行的两次提交之一保存了 Git 的 index(也称为 暂存区 )。 git stash 所做的另一个提交保存了您的工作树。

然后,在完成这两个提交后,git stash 运行s git reset --hard。这就是删除所有工作的原因:git stash savegit stash pushgit reset --hard 步骤。4 通常 git reset --hard 非常具有破坏性,但是git stash 首先做出了一些 提交 的事实使得这没问题(或 okay-ish)。


4这里的 savepush 动词之间的区别是历史性的:对于正常的存储情况,它们都做同样的事情。然而,在 Git 2.9 左右,git stash 学会了“部分存储”。为此,Git 人员不得不创建一个新动词 push,因为原始动词 save 计划不周。默认的 git stash 操作是 save-or-push 操作,当您不使用带有 git stash push 的路径规范时,它会进行完全保存并因此进行完全重置。当你使用路径规范时,这会将最终的clean-out从git reset --hard更改为更具选择性的东西。

这个 git stash push partial-save 早期的代码有很多错误,所以我建议在 Git 2.17 之前不要使用它。好吧,我通常建议完全避免 git stash,除非在一些非常有限的情况下,但我的意思是如果你 打算使用 git stash push 使用部分推送功能,在Git.

的这些中间版本中要格外小心