如何在git reset之后恢复我的故事板--hard HEAD ^?

时间:2017-04-18 02:13:48

标签: ios swift xcode git

大约一个星期前,我正在将我的.gitignore文件推送到我的存储库,并且遇到了一些小问题,最后想出来了,但注意到我的所有故事板都在存储库中。在天才的推动下,我看着让他们离开那里,发现了上面的git reset命令,然后把它放到我的终端并拍拍自己的背部,生活还在继续。我刚刚意识到安装了一些cocoapods之后,我花了几周工作的所有故事板都消失了,把两个和两个放在一起。我花了最后一小时阅读了类似的问题,但在阅读了一段时间后却找不到任何东西,我想知道是否有其他xcode用户遇到同样的问题并且可以提供帮助。

我还应该补充一点,我只是将故事板添加到舞台上并且在重置时尚未提交它们,所以今天我使用git reflog命令希望它们在丢失并找到了。我读过垃圾收集一个月没有发生,所以我不想(我希望)他们刚刚离开

我今天下载了AWS SDK,而且目前所有的git reflog命令似乎都在显示。我是否需要进一步回滚git rest HEAD {}命令?

非常感谢!

1 个答案:

答案 0 :(得分:2)

您在评论中注意到您执行了git stash

这是一个重要的信息,它改变了一切。幸运的是,它也使恢复变得更加容易。特别是它意味着你丢失的文件不是"悬空blob"并且 do 保存了原始名称。 (顺便提一下,git stash表示git stash save;我会使用下面的较长表格将其与其他git stash命令区分开来。)

最简单的恢复方法是使用git stash branch。选择分支名称,即您尚未拥有的名称。为了说明,我将使用saveme,这是一个可怕的名称,你应该选择一个更好的名称。

git stash branch saveme

这将使用您现有的git stash,使用当前运行git stash save时的提交创建分支。然后,它会将您的索引(暂存区域)恢复为您运行git stash save时的工作树状态,使其恢复到您运行时的状态{ {1}}。您现在可以提交索引:

git stash save

然后提交其余的工作树,如果还有其他事情需要提交:

git commit -m 'save index as a commit'

我将在这个答案的最后(在另一个编辑中)添加一个图表,说明整个序列发生了什么,从第一个git add --all git commit -m 'save everything else as a commit too' 开始并经过git addgit stash save以及最后的git reset --hard HEAD^

有一点需要注意:您的索引和工作树必须干净才能使用git stash branch。如果您有未提交的工作,您可能应该立即提交,或者使用git stash branch将其全部删除。当然,任何一个都有后果:

  • 如果您运行另一个git reset --hard,则先前保存的藏匿点会被推送到#34;从git stash savestash@{0}。然后你必须使用:

    stash@{1}

    将该存储转换为分支。

  • 如果您选择使用git stash branch saveme stash@{1} ,则会丢失任何未提交的作品,因此请确保此操作正常。

图示

让我们来看一个假设的终端会话,看看你工作时你的提交和分支会发生什么。

git reset --hard

此时,您正在使用Git工作树。工作树是您的文件处于正常形式的位置,计算机的其余部分(和您)可以使用,而不是Git专用表单,Git保存 的每个版本em>您或其他任何人提交的文件。你在某些分支上 - 让我们说$ cd my-git-project ,只是为了具体。这个分支有一些提交,以Git调用该分支的 tip 提交结束。分支名称会记住此提示提交的哈希ID:

master

每个大写字母代表一个普通的普通提交。 (换句话说,这些代表了每个提交的实际名称的难以理解的哈希ID。)提交...--F--G--H <-- master 是最新的。如果您的索引/暂存区域和工作树是&#34; clean&#34;,则其中的文件与提交H中的文件匹配。

现在你做了一些改变,然后进行部分或全部修改:

H

暂存区域,也就是索引,现在不是&#34;干净&#34;:它不再匹配提交$ ... edit some files ... $ git add file1 file2 ... 。相反,它包含已编辑和添加的文件的副本。

您的工作树可能与您的索引匹配也可能不匹配。如果 匹配你的索引,并且如果你要运行H,Git会从你的索引中做出一个新的提交(那是索引/登台区域是什么)因为,主要是:构建下一个提交),然后你的索引将匹配你的提交并且是干净的。如果您的工作树与您的索引匹配,那么那也是干净的。这看起来像是:

git commit

其中...--F--G--H--I <-- master 是新提交,由您的索引构成。

相反,你跑了I。这样做是做两个提交,两者都不在分支上:

git stash save

第一个(小写...--F--G--H <-- master |\ i-w <-- stash )提交是i提交的相同的提交。它不在分支git commit上;它是这个两次提交&#34;藏匿袋的一部分&#34;。第二个提交master是特殊的:它看起来像Git的其余部分就像是一个合并提交,但实际上它只是提交了你的工作树状态,即使这样做也是如此。与w中的索引状态相同

在进行这两个存储包提交后,i重置(清除)索引和工作树,即git stash。所以现在你的索引和工作树匹配再次提交git reset --hard HEAD

接下来,你说你跑了H。这会做三个事情:它将索引和工作树状态重置为所选提交的状态,即git reset --hard HEAD^之前的状态;它使名称H 也指向所选的提交。所以现在您的存储库看起来像这样:

master

请注意,隐藏包仍然存在,仍然可以通过名称...--F--G <-- master \ H [remembered in reflogs, *and* preserved via the stash] |\ i-w <-- stash 找到。两个stash-bag提交记住了它的哈希ID提交stash。同时,名称H现在会记住提交master的哈希ID,而您的索引和工作树是&#34; clean&#34;,即匹配G的哈希值

如果您现在运行G,这就是Git在提交方面的作用:

git stash branch saveme

...--F--G <-- master \ H <-- saveme |\ i-w [abandoned] 提交重新加载索引,并从i提交重新加载工作树。如果你现在运行w,你会得到:

git commit

因为Git将索引保存为新提交...--F--G <-- master \ H--I <-- saveme 。工作树保持不变;如果它在I方面干净了,那么它现在都是干净的,如果没有,你可以I任何剩余的更改并提交它们:

git add

现在所有内容都会永久保存(或直到您删除...--F--G <-- master \ H--I--J <-- saveme 分支),这些普通提交可以通常的方式使用。请注意,您使用saveme投放到回收站的提交H已在新分支上返回

原始答案

  

我还应该补充一点,我只是将故事板添加到舞台上,并且在重置时还没有提交它们......

这会让事情变得更难,因为:

  

...今天我正在使用git reset --hard HEAD^命令

git reflog仅查看已弃用的提交

  

......希望他们在迷路中找到。

他们可能仍然是! &#34;迷失并找到了#34;与reflogs分开。

  

我读过垃圾收集一个月没发生所以我不想(我希望)他们刚刚离开

30天的宽限期专门用于在reflog中记住的 commit 对象,而这些对象不是。但是,所有对象都会获得14天的宽限期。时钟从git reflog文件到暂存区域时开始。 (即使一旦时钟耗尽,也需要稍后git add才能使文件消失,但很难知道何时会发生这种情况。)

实际上找到你的文件有点棘手。运行:

git gc --auto

,正如the documentation所说:

  

git fsck --lost-found

     
    将悬空对象写入.git / lost-found / commit /或   .git / lost-found / other /,具体取决于类型。如果对象是blob,   内容被写入文件,而不是其对象   名称

由于你做了--lost-found这些文件,并且他们可能从未进行过任何提交,因此他们将会&&#34;悬挂&#34;对象类型&#34; blob&#34;。 git add命令将打印一堆难以理解的哈希名称。然后,您可以切换到git fsck目录并检查其中的所有文件,这些文件都具有这些哈希名称。在所有这些文件中,您.git/lost-found/other/ ed的内容将会出现。

对于每个此类文件,确定是否应将其保存在合理的文件名下,并将文件从git add区域移出到该名称之一,然后将该文件恢复。