当前位置:  开发笔记 > 编程语言 > 正文

如何恢复Git中丢失的存储?

如何解决《如何恢复Git中丢失的存储?》经验,为你挑选了15个好方法。

我经常使用git stashgit stash pop保存和恢复工作树中的更改.昨天我的工作树上有一些变化,我已经藏起来了,然后我对工作树做了更多改动.我想回去查看昨天发生的变化,但git stash pop似乎删除了对相关提交的所有引用.

我知道如果我使用git stash那么.git/refs/stash包含用于创建存储的提交的引用.而.git/logs/refs/stash包含整个存储.但那些参考文献已经消失了git stash pop.我知道提交仍然在我的存储库中,但我不知道它是什么.

有没有一种简单的方法来恢复昨天的隐藏提交引用?

请注意,这对我来说并不重要,因为我有每日备份,可以回到昨天的工作树来获取我的更改.我问,因为必须有一个更简单的方法!



1> Aristotle Pa..:

一旦你知道你删除的存储提交的哈希值,你可以将它作为存储应用:

git stash apply $stash_hash

或者,您可以为其创建单独的分支

git branch recovered $stash_hash

之后,您可以使用所有常规工具执行任何操作.当你完成后,只需将树枝吹走.

找到哈希

如果您刚刚弹出它并且终端仍然打开,您仍然会git stash pop在屏幕上打印哈希值(谢谢,Dolda).

否则,你可以在Linux,Unix或Git Bash for Windows中找到它:

git fsck --no-reflog | awk '/dangling commit/ {print $3}'

...或者使用Powershell for Windows:

git fsck --no-reflog | select-string 'dangling commit' | foreach { $bits = $_ -split ' '; echo $bits[2];}

这将向您显示提交图提示中的所有提交,这些提交不再从任何分支或标记引用 - 每个丢失的提交(包括您创建的每个存储提交)都将位于该图中的某个位置.

找到所需存储提交的最简单方法可能是将该列表传递给gitk:

gitk --all $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' )

...或者如果使用Powershell for Windows,请查看emragins的答案.

这将启动一个存储库浏览器,显示存储库中的每个提交,无论它是否可访问.

如果您喜欢在控制台上通过单独的GUI应用程序使用漂亮的图形,则可以替换gitkgit log --graph --oneline --decorate.

要查找存储提交,请查找此表单的提交消息:

        在somebranch上的 WIP :commithash一些旧的提交消息

注意:如果您没有提供消息,则提交消息将仅以此形式(以"WIP on"开头)git stash.


WIP :

杰德尔把话说出了我的话.这篇文章保存了我的工作:)我只想添加 - 记住你工作的日期,无论你丢失了什么,都可以更轻松地浏览gitk以寻找你想要的东西.
如果你知道什么时候发生了丢弃,你可以通过增加时间来使用这个单行来获取悬空提交列表:`git fsck --no-reflog | awk'/ dangling commit/{print $ 3}'| xargs -L 1 git --no-pager show -s --format ="%ci%H"| 排序`最后一个条目可能就是你要"存储申请"的条目.
值得一提的是,如果在存储时没有提供自己的消息(即通过执行`git stash save""`),提交消息将只有字符串"WIP".
@Codey:因为PowerShell.我不知道MsysGit是否附带了AWK二进制文件.谷歌搜索告诉我像'%{$ _.分裂('')[2]; ``应该在PowerShell中的`awk`命令中执行相当于`{print $ 3}`的操作,但我没有Windows系统来测试它,你还需要一个等价的`/ dangling commit /`部分.无论如何,只需运行`git fsck --no-reflog`并查看输出.你想要"悬挂提交"行的哈希.

2> Dolda2000..:

如果您没有关闭终端,只需查看输出git stash pop,您将获得已删除存储的对象ID.它通常看起来像这样:

$ git stash pop
[...]
Dropped refs/stash@{0} (2ca03e22256be97f9e40f08e6d6773c7d41dbfd1)

(注意,git stash drop也会生成相同的行.)

为了获得那些存储,只需运行git branch tmp 2cae03e,你就可以将它作为一个分支.要将其转换为存储,请运行:

git stash apply tmp
git stash

将它作为分支也允许您自由地操纵它; 例如,樱桃挑选或合并它.


您也可以执行`git stash apply commitid`然后`git stash`来获取新的存储.
请注意,如果git自动合并存储并且存在冲突,则不会向您显示哈希.
@James:再说一次,如果这些冲突是运行`git stash pop`的结果,它也不会丢弃存储,所以这通常不是问题.
这也适用于恢复"git stash drop"

3> Wade..:

只是想提到对已接受的解决方案的这一补充.我第一次尝试这种方法时并不是很明显(也许应该是这样),但是要从哈希值中应用存储,只需使用"git stash apply":

$ git stash apply ad38abbf76e26c803b27a6079348192d32f52219

当我刚接触git时,这对我来说并不清楚,我正在尝试"git show","git apply","patch"等的不同组合.


请注意,这会将(存储!)存储应用于当前工作树.如果树是脏的,您可能要先使用临时分支或存储,从SHA-1应用存储,再次存储,然后弹出第二个到最后一个存储(称为存储@ {1}).

4> Senthil A Ku..:

要获取仍在存储库中但不再可访问的存储列表:

git fsck --unreachable | grep commit | cut -d" " -f3 | xargs git log --merges --no-walk --grep=WIP

如果您为藏匿物提供了标题,请将-grep=WIP命令末尾的"WIP"替换为消息的一部分,例如-grep=Tesselation.

该命令正在为"WIP"进行grepping,因为存储的默认提交消息在表单中 WIP on mybranch: [previous-commit-hash] Message of the previous commit.



5> Greg Hewgill..:

我刚刚构建了一个命令,帮助我找到丢失的存储提交:

for ref in `find .git/objects | sed -e 's#.git/objects/##' | grep / | tr -d /`; do if [ `git cat-file -t $ref` = "commit" ]; then git show --summary $ref; fi; done | less

这将列出.git/objects树中的所有对象,找到类型为commit的对象,然后显示每个对象的摘要.从这一点来看,只需查看提交内容即可找到合适的"WIP on work:6a9bb2"("work"是我的分支,619bb2是最近的提交).

我注意到,如果我使用"git stash apply"而不是"git stash pop"我不会遇到这个问题,如果我使用"git stash save message ",那么提交可能更容易找到.

更新:根据内森的想法,这变得更短:

for ref in `git fsck --unreachable | grep commit | cut -d' ' -f3`; do git show --summary $ref; done | less



6> Nathan Jones..:

git fsck --unreachable | grep commit应该显示sha1,虽然它返回的列表可能非常大.git show 将显示它是否是您想要的提交.

git cherry-pick -m 1 将提交合并到当前分支.



7> Colin Hebert..:

如果你想要重建一个丢失的存储,你需要先找到丢失的存储的哈希值.

正如亚里士多德Pagaltzis所建议的,git fsck应该帮助你.

就个人而言,我使用我的log-all别名向我展示每次提交(可恢复的提交)以更好地了解情况:

git log --graph --decorate --pretty=oneline --abbrev-commit --all $(git fsck --no-reflogs | grep commit | cut -d' ' -f3)

如果您只查看"WIP on"消息,则可以进行更快速的搜索.

一旦你知道你的sha1,你只需更改你的存储reflog以添加旧的存储:

git update-ref refs/stash ed6721d

你可能更愿意有一个相关的消息,所以a -m

git update-ref -m "$(git log -1 --pretty=format:'%s' ed6721d)" refs/stash ed6721d

你甚至想用它作为别名:

restash = !git update-ref -m $(git log -1 --pretty=format:'%s' $1) refs/stash $1



8> emragins..:

使用gitk等效的Windows PowerShell:

gitk --all $(git fsck --no-reflog | Select-String "(dangling commit )(.*)" | %{ $_.Line.Split(' ')[2] })

可能有一种更有效的方法在一个管道中执行此操作,但这可以完成这项工作.



9> Shaheen Ghia..:

我喜欢亚里士多德的方法,但不喜欢使用GITK ......因为我习惯于从命令行使用GIT.

相反,我接受了悬挂提交并将代码输出到DIFF文件以供我在代码编辑器中查看.

git show $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' ) > ~/stash_recovery.diff

现在,您可以将生成的diff/txt文件(在主文件夹中)加载到txt编辑器中,并查看实际代码和生成的SHA.

然后就用吧

git stash apply ad38abbf76e26c803b27a6079348192d32f52219



10> Vivek Kumar..:

您可以通过在终端中写入此命令来列出所有无法访问的提交 -

git fsck --unreachable

检查无法访问的提交哈希 -

git show hash

如果你发现藏匿物品,最后申请 -

git stash apply hash



11> Can Tecim..:

在使用git v2.6.4的OSX中,我只是意外地运行了git stash drop,然后我通过下面的步骤找到了它

如果您知道藏匿名称,请使用:

$ git fsck --unreachable | grep commit | cut -c 20- | xargs git show | grep -B 6 -A 2

否则你将通过手动找到结果中的ID:

$ git fsck --unreachable | grep commit | cut -c 20- | xargs git show

然后,当你发现commit-id刚刚点击git stash时,应用{commit-id}

希望这可以帮助别人



12> RobbyD..:

为什么人们会问这个问题?因为他们还不了解或了解reflog.

这个问题的大多数答案给出了长命令,几乎没有人会记得.所以人们进入这个问题并复制粘贴他们认为他们需要的东西并且几乎立即忘记它.

我会建议所有人用这个问题来检查reflog(git reflog),不仅如此.一旦你看到所有提交的列表,有一百种方法可以找出你正在寻找的提交,并挑选它或从中创建一个分支.在这个过程中,您将了解各种基本git命令的reflog和有用选项.



13> Phil..:

我想添加到已接受的解决方案另一个好方法来完成所有更改,当你没有gitk可用或没有X输出时.

git fsck --no-reflog | awk '/dangling commit/ {print $3}' > tmp_commits

for h in `cat tmp_commits`; do git show $h | less; done

然后你会得到一个接一个显示的哈希的所有差异.按'q'进入下一个差异.



14> 小智..:

我无法在一个简单的命令窗口(在我的例子中是Windows 7)中获得在Windows上工作的任何答案.awk,grepSelect-string没有被识别为命令.所以我尝试了一种不同的方法:

第一次运行: git fsck --unreachable | findstr "commit"

将输出复制到记事本

找到替换"无法访问提交" start cmd /k git show

看起来像这样:

start cmd /k git show 8506d235f935b92df65d58e7d75e9441220537a4 start cmd /k git show 44078733e1b36962571019126243782421fcd8ae start cmd /k git show ec09069ec893db4ec1901f94eefc8dc606b1dbf1 start cmd /k git show d00aab9198e8b81d052d90720165e48b287c302e

另存为.bat文件并运行它

该脚本将打开一堆命令窗口,显示每个提交

如果你找到了你正在寻找的那个,请运行: git stash apply (your hash)

可能不是最好的解决方案,但对我有用



15> 小智..:

亚里士多德接受的答案将显示所有可达的提交,包括非类似stash的提交.滤除噪音:

git fsck --no-reflog | \
awk '/dangling commit/ {print $3}' | \
xargs git log --no-walk --format="%H" \
  --grep="WIP on" --min-parents=3 --max-parents=3

这将只包括具有3个父提交(存储将具有)的提交,并且其消息包括"WIP on".

请记住,如果您使用消息(例如git stash save "My newly created stash")保存了存储,则会覆盖默认的"WIP on ..."消息.

您可以显示有关每个提交的更多信息,例如显示提交消息,或将其传递给git stash show:

git fsck --no-reflog | \
awk '/dangling commit/ {print $3}' | \
xargs git log --no-walk --format="%H" \
  --grep="WIP on" --min-parents=3 --max-parents=3 | \
xargs -n1 -I '{}' bash -c "\
  git log -1 --format=medium --color=always '{}'; echo; \
  git stash show --color=always '{}'; echo; echo" | \
less -R

推荐阅读
echo7111436
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有