我经常使用 git stash 和 git stash pop 来保存和恢复工作树中的更改。昨天我在我的工作树中进行了一些更改,我已经隐藏并弹出了这些更改,然后我对我的工作树进行了更多更改。我想返回并查看昨天隐藏的更改,但 git stash pop 似乎删除了对相关提交的所有引用。
我知道如果我使用 git stash 那么 .git/refs/stash 包含 用于创建存储的提交的引用。 .git/logs/refs/stash 包含整个存储。但是这些引用在 git stash pop 之后消失了。我知道提交仍在我的存储库中的某个地方,但我不知道它是什么。
有没有一种简单的方法可以恢复昨天的存储提交参考?
请注意,今天这对我来说并不重要,因为我每天都有备份,并且可以返回到昨天的工作树来获取我的更改。我问是因为必须有更简单的方法!
huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!
一旦您知道您删除的存储提交的哈希值,您就可以将其应用为存储:
git stash apply $stash_hash
或者,您可以为它创建一个单独的分支
git branch recovered $stash_hash
之后,您可以使用所有常规工具做任何您想做的事情。完成后,只需将树枝吹走。
查找哈希
如果您刚刚弹出它并且终端仍然打开,您将still have the hash value printed by git stash pop on screen(谢谢,Dolda)。
否则,您可以在 Linux、Unix 或 Windows 的 Git Bash 上使用它:
git fsck --no-reflog | awk '/dangling commit/ {print $3}'
…或使用适用于 Windows 的 Powershell:
git fsck --no-reflog | select-string 'dangling commit' | foreach { $_.ToString().Split(" ")[2] }
这将在提交图的提示处向您显示不再从任何分支或标签引用的所有提交——每个丢失的提交,包括您曾经创建的每个存储提交,都将在该图中的某个位置。
找到您想要的存储提交的最简单方法可能是将该列表传递给 gitk:
gitk --all $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' )
…如果使用适用于 Windows 的 Powershell,请参阅 the answer from emragins。
这将启动一个存储库浏览器,向您显示存储库中的每一次提交,无论它是否可访问。
如果您更喜欢控制台上的漂亮图表而不是单独的 GUI 应用程序,则可以将其中的 gitk 替换为 git log --graph --oneline --decorate。
要发现 stash 提交,请查找以下形式的提交消息:
在某个分支上的 WIP:commithash 一些旧的提交消息
注意:如果您在执行 git stash 时未提供消息,则提交消息只会采用这种形式(以“WIP on”开头)。
杰德尔从我嘴里说出来。这篇文章挽救了我的工作 :) 我想补充一点——记住你工作的日期,无论你丢失了什么,都可以更容易地浏览 gitk 来寻找你想要的东西。
@Codey:因为 PowerShell。我不知道 MsysGit 是否提供 AWK 二进制文件。谷歌搜索告诉我,像 %{ $_.Split(' ')[2]; } 之类的东西应该在 PowerShell 中的 awk 命令中执行相当于 {print $3} 的操作,但我没有 Windows 系统来测试它,您仍然需要 {4 } 部分。无论如何,只需运行 git fsck --no-reflog 并查看输出。你想要来自“悬空提交”的哈希值线。
值得一提的是,如果您在存储时没有提供自己的消息(即通过执行 git stash save ""),则提交消息将只有字符串“WIP”。
如果您知道丢弃发生的时间,您可以使用这个单行代码通过增加时间来获取悬空提交的列表:git fsck --no-reflog | awk '/dangling commit/ {print $3}' | xargs -L 1 git --no-pager show -s --format="%ci %H" | sort 最后一个条目可能是您想要的stash apply。
git stash apply {ref} 恢复了丢弃的存储! git 太好了,应该是非法的!
huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。
如果您没有关闭终端,只需查看 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 pop 输出中没有 SHA。 :(
@Honey:这就是 git stash pop 的重点。如果您想应用存储而不删除它,请改用 git stash apply。此外,如果您想将更改应用到多个分支,您也可以选择选择提交。
huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。
只是想在已接受的解决方案中提及此添加。我第一次尝试这种方法时并不是很明显(也许应该是这样),但是要从哈希值应用存储,只需使用“git stash apply”:
$ git stash apply ad38abbf76e26c803b27a6079348192d32f52219
当我刚接触 git 时,我并不清楚,我正在尝试“git show”、“git apply”、“patch”等的不同组合。
请注意,这适用于(duh!)存储到当前工作树。如果树脏了,您可能想要使用临时分支或先存储,从 SHA-1 应用存储,再次存储,然后弹出倒数第二个存储(称为 stash@{1})。
huntsbot.com – 高效赚钱,自由工作
要获取仍在您的存储库中但不再可访问的存储列表:
git fsck --unreachable | grep commit | cut -d" " -f3 | xargs git log --merges --no-walk --grep=WIP
如果您为您的存储指定了标题,请将命令末尾的 -grep=WIP 中的“WIP”替换为您的消息的一部分,例如 -grep=Tesselation。
该命令正在搜索“WIP”,因为存储的默认提交消息采用 WIP on mybranch: [previous-commit-hash] Message of the previous commit. 形式
找到提交后,使用 git stash apply
echo 'git fsck --unreachable | grep 提交 |剪切-d" "-f3 | xargs git log --merges --no-walk --grep=WIP' >/usr/local/bin/git-stashlog; chmod a+rx /usr/local/bin/git-stashlog # git stashlog
或者,您可以将其作为别名添加到您的 .gitconfig(命令前带有 !)。
救了我的培根——不是真的,但救了我重新编码工作的日子——感激——考虑到我最近才放弃,我刚刚从你的命令输出中选择了顶部的 SHA——然后.... git stash apply SHA ...正如其他答案中提到的 - 许多谢谢
这适用于查找丢失的提交而不是接受的答案!当您找到提交时,使用 git stash apply 应用它
太棒了,WIP 的 grep 对我来说是关键。
打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!
我刚刚构建了一个命令来帮助我找到丢失的存储提交:
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”那么提交可能更容易找到。
更新:有了 Nathan 的想法,这变得更短:
for ref in `git fsck --unreachable | grep commit | cut -d' ' -f3`; do git show --summary $ref; done | less
huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。
使用 gitk 的 Windows PowerShell 等效项:
gitk --all $(git fsck --no-reflog | Select-String “(dangling commit )(.*)” | %{ $_.Line.Split(’ ')[2] })
可能有一种更有效的方法可以在一个管道中执行此操作,但这可以完成工作。
huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!
git fsck --unreachable | grep commit 应该显示 sha1,尽管它返回的列表可能非常大。 git show 将显示它是否是您想要的提交。
git cherry-pick -m 1 会将提交合并到当前分支。
与HuntsBot一起,探索全球自由职业机会–huntsbot.com
如果要重新存储丢失的存储,则需要先找到丢失的存储的哈希。
正如 Aristotle 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,你只需改变你的 stash reflog 来添加旧的 stash :
git update-ref refs/stash ed6721d
您可能更喜欢关联消息,因此 -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
huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。
然而,-d\\ 应该是 -d\ (或更清晰的 -d' ')
出现错误:“致命:不明确的参数‘悬空’:未知修订版或路径不在工作树中。”
您还需要用引号括起子命令 git update-ref -m "$(git log -1 --pretty=format:'%s' ed6721d)" refs/stash ed6721
太感谢了!!!第一个命令为我节省了一周的工作量!!!
打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!
我喜欢亚里士多德的方法,但不喜欢使用 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
huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。
您可以通过在终端中编写此命令来列出所有无法访问的提交 -
git fsck --unreachable
检查无法访问的提交哈希 -
git show hash
如果您找到隐藏的物品,最后申请 -
git stash apply hash
huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。
我最喜欢的是这个单行:
git log --oneline $( git fsck --no-reflogs | awk '/dangling commit/ {print $3}' )
这与 this answer 基本相同,但要短得多。当然,您仍然可以添加 --graph 以获得树状显示。
在列表中找到提交后,使用
git stash apply THE_COMMIT_HASH_FOUND
对我来说,使用 --no-reflogs 确实揭示了丢失的存储条目,但 --unreachable (在许多其他答案中发现)没有。
当你在 Windows 下时,在 git bash 上运行它。
致谢:上述命令的详细信息来自 https://gist.github.com/joseluisq/7f0f1402f05c45bac10814a9e38f81bf
这对我在 Mac OSX git 版本 2.31.1 上运行良好,而 gitk 在尝试打开窗口时产生错误。我也尝试了信用链接,但在撰写此评论时,它在命令中包含语法错误,括号前缺少 $。或许还值得一提的是,如果您至少可以记住存储名称的一部分,您可以通过 grep 将输出通过管道传输来找到它。
原文链接:https://www.huntsbot.com/qa/w7qy/how-to-recover-a-dropped-stash-in-git?lang=zh_CN&from=csdn
huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。