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

发布于 2024-07-05 16:37:32 字数 342 浏览 7 评论 0原文

我经常使用 git stash 和 git stash pop 来保存和恢复工作树中的更改。 昨天,我对工作树进行了一些更改,将其隐藏并弹出,然后对工作树进行了更多更改。 我想返回并查看昨天隐藏的更改,但 git stash pop 似乎删除了对相关提交的所有引用。

我知道如果我使用 git stash 则 .git/refs/stash 包含用于创建存储的提交的引用。 .git/logs/refs/stash 包含整个存储。 但这些引用在 git stash pop 后就消失了。 我知道该提交仍在我的存储库中的某个位置,但我不知道它是什么。

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

I frequently use git stash and git stash pop to save and restore changes in my working tree. Yesterday, I had some changes in my working tree that I had stashed and popped, and then I made more changes to my working tree. I'd like to go back and review yesterday's stashed changes, but git stash pop appears to remove all references to the associated commit.

I know that if I use git stash then .git/refs/stash contains the reference of the commit used to create the stash. And .git/logs/refs/stash contains the whole stash. But those references are gone after git stash pop. I know that the commit is still in my repository somewhere, but I don't know what it was.

Is there an easy way to recover yesterday's stash commit reference?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(25

青衫儰鉨ミ守葔 2024-07-12 16:37:33

知道大致的文件名及其位置,并且能够通过 greping 悬挂提交查找路径来找到已删除的存储文件

for i in $(git fsck --no-reflogs | awk '/dangling commit/ {print $3}'); do
  if git log -5 --name-only -u $i | grep -q "<path-to-files>/.*<partial-file-name>.*"; then
    echo "found something in commit $i";
  fi;
done

Knowing the approximate file name and it's location, and was able to find dropped stash files grepping dangling commits for path

for i in $(git fsck --no-reflogs | awk '/dangling commit/ {print $3}'); do
  if git log -5 --name-only -u $i | grep -q "<path-to-files>/.*<partial-file-name>.*"; then
    echo "found something in commit $i";
  fi;
done
违心° 2024-07-12 16:37:33

不完全是获得存储的答案,但如果目标是获得未提交的更改,这些更改首先存储然后弹出到另一个分支中,但对于两者都意味着并按以下方式完成:

  1. branch_a 中进行更改
  2. < code>git stash
  3. branch_a 创建branch_b
  4. git stash apply

然后恢复对 branch_a 未提交的更改:

  1. git checkout分支_a
  2. > <代码> git合并分支_b
  3. > <代码> git重置HEAD〜1

Not exactly an answer to get a stash but if the goal is to get uncommited changes that were first stashed and then popped in another branch but meant for both and done in the following way:

  1. Make changes in branch_a
  2. git stash
  3. Make branch_b from branch_a
  4. git stash apply

Then to restore the uncommited changes to branch_a:

  1. git checkout branch_a
  2. git merge branch_b
  3. git reset HEAD~1
长安忆 2024-07-12 16:37:33

您可以逐步遵循以下过程:

1- 使用下面列出所有无法访问的提交
git fsck --unreachable

2- 显示无法访问的提交哈希
git show hash

3-复制所有日志,您可以看到类似日志,无法访问的blob,提交,树。

4-应用 git stash 和具有提交哈希的日志
git stash apply [替换哈希]

You can follow the below process step by step:

1- use below to list all unreachable commits
git fsck --unreachable

2- to show unreachable commit hash by
git show hash

3- copy all log, you can see log like, unreachable blob, commit, tree.

4- apply git stash with log having commit hash
git stash apply [replace hash]

葵雨 2024-07-12 16:37:33

这对我(2022 年)有用,可以从 Windows 环境恢复 git 中意外删除的存储。

这些步骤概述了如何恢复任何已删除的 git 存储或分支(假设它尚未被垃圾收集永久删除)。

  1. 导航到您的项目所在的目录。

  2. 输入命令:git fsck --no-reflogs | 找到“悬空提交”
    输入图像描述这里

  3. 将会出现悬空提交的哈希值列表。 这些将包含已删除的分支和存储。 首先复制并粘贴列表末尾附近的哈希值以查找您的存储或分支。 例如,使用命令:git log -1 [hash]

  4. 如果相应的哈希与您尝试恢复的内容匹配,请使用以下命令来恢复它”
    git stash apply [哈希]

This worked for me (in 2022) with recovering my accidently deleted stash in git from a windows environment.

These steps outline how to recover any deleted git stashes or branches (assuming it has not been permanently delete by garbage collection).

  1. Navigate to the directory where your project located.

  2. Enter the command: git fsck --no-reflogs | find "dangling commit"
    enter image description here

  3. A list of hashes for dangling commits will appear. These will consist of branches and stashes that were deleted. Start with copy and pasting the hashes near the end of the list to find your stash or branch. For example, use the command: git log -1 [hash]

  4. If the corresponding hash matches what you are trying to recover, use the following command to restore it"
    git stash apply [hash]

你的他你的她 2024-07-12 16:37:33

使用 gitk 的 Windows PowerShell 等效项:

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

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

Windows PowerShell equivalent using gitk:

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

There is probably a more efficient way to do this in one pipe, but this does the job.

允世 2024-07-12 16:37:33

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

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 树中的所有对象,找到提交类型的对象,然后显示每个对象的摘要。 从这一点来看,只需查看提交以找到合适的“工作中的 WIP:6a9bb2”(“工作”是我的分支,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

I just constructed a command that helped me find my lost stash commit:

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

This lists all the objects in the .git/objects tree, locates the ones that are of type commit, then shows a summary of each one. From this point it was just a matter of looking through the commits to find an appropriate "WIP on work: 6a9bb2" ("work" is my branch, 619bb2 is a recent commit).

I note that if I use "git stash apply" instead of "git stash pop" I wouldn't have this problem, and if I use "git stash save message" then the commit might have been easier to find.

Update: With Nathan's idea, this becomes shorter:

for ref in `git fsck --unreachable | grep commit | cut -d' ' -f3`; do git show --summary $ref; done | less
魂牵梦绕锁你心扉 2024-07-12 16:37:33

git fsck --无法访问 | grep commit 应该显示 sha1,尽管它返回的列表可能相当大。 git show 将显示这是否是您想要的提交。

gitcherry-pick -m 1 会将提交合并到当前分支。

git fsck --unreachable | grep commit should show the sha1, although the list it returns might be quite large. git show <sha1> will show if it is the commit you want.

git cherry-pick -m 1 <sha1> will merge the commit onto the current branch.

你是我的挚爱i 2024-07-12 16:37:33

如果您想重新存储丢失的存储,您需要首先找到丢失的存储的哈希值。

正如 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,您只需更改您的存储引用日志即可添加旧的存储:

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

If you want to restash a lost stash, you need to find the hash of your lost stash first.

As Aristotle Pagaltzis suggested a git fsck should help you.

Personally I use my log-all alias which show me every commit (recoverable commits) to have a better view of the situation :

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

You can do an even faster search if you're looking only for "WIP on" messages.

Once you know your sha1, you simply change your stash reflog to add the old stash :

git update-ref refs/stash ed6721d

You'll probably prefer to have an associated message so a -m

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

And you'll even want to use this as an alias :

restash = !git update-ref -m $(git log -1 --pretty=format:'%s' $1) refs/stash $1
℡Ms空城旧梦 2024-07-12 16:37:33

我最喜欢的是这句话:

git log --oneline  $( git fsck --no-reflogs | awk '/dangling commit/ {print $3}' )

这基本上与这个答案相同,但要短得多。 当然,你仍然可以添加--graph来获得树状显示。

当您在列表中找到提交后,请使用

git stash apply THE_COMMIT_HASH_FOUND

对于我来说,使用 --no-reflogs 确实显示了丢失的存储条目,但是 --unreachable (如在许多其他答案)没有。

当你在 Windows 下时,在 git bash 上运行它。

鸣谢:上述命令的详细信息取自 https://gist.github.com/joseluisq/7f0f1402f05c45bac10814a9e38f81bf< /a>

My favorite is this one-liner:

git log --oneline  $( git fsck --no-reflogs | awk '/dangling commit/ {print $3}' )

This is basically the same idea as this answer but much shorter. Of course, you can still add --graph to get a tree-like display.

When you have found the commit in the list, apply with

git stash apply THE_COMMIT_HASH_FOUND

For me, using --no-reflogs did reveal the lost stash entry, but --unreachable (as found in many other answers) did not.

Run it on git bash when you are under Windows.

Credits: The details of the above commands are taken from https://gist.github.com/joseluisq/7f0f1402f05c45bac10814a9e38f81bf

镜花水月 2024-07-12 16:37:33

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

git fsck --unreachable

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

git show hash

如果找到隐藏的项目,最后应用 -

git stash apply hash

You can list all unreachable commits by writing this command in terminal -

git fsck --unreachable

Check unreachable commit hash -

git show hash

Finally apply if you find the stashed item -

git stash apply hash
热情消退 2024-07-12 16:37:33

我喜欢亚里士多德的方法,但不喜欢使用 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

I liked Aristotle's approach, but didn't like using GITK... as I'm used to using GIT from the command line.

Instead, I took the dangling commits and output the code to a DIFF file for review in my code editor.

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

Now you can load up the resulting diff/txt file (its in your home folder) into your txt editor and see the actual code and resulting SHA.

Then just use

git stash apply ad38abbf76e26c803b27a6079348192d32f52219
我三岁 2024-07-12 16:37:33

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

如果您知道存储的名称,则使用:

$ git fsck --unreachable | grep 提交 | 切-c 20- | xargs git 显示 | grep -B 6 -A 2 <存储的名称>

否则,您将通过手动方式从结果中找到 ID:

$ git fsck --unreachable | grep 提交 | 切-c 20- | xargs git show

然后,当你找到 commit-id 时,只需点击 git stash apply {commit-id}

希望这可以快速帮助别人

In OSX with git v2.6.4, I just run git stash drop accidentally, then I found it by going trough below steps

If you know name of the stash then use:

$ git fsck --unreachable | grep commit | cut -c 20- | xargs git show | grep -B 6 -A 2 <name of the stash>

otherwise you will find ID from the result by manually with:

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

Then when you find the commit-id just hit the git stash apply {commit-id}

Hope this helps someone quickly

我为君王 2024-07-12 16:37:33

为什么人们会问这个问题? 因为他们还不知道或理解转发日志。

这个问题的大多数答案都给出了很长的命令和几乎没有人会记住的选项。 因此,人们遇到这个问题时,会复制粘贴他们认为需要的任何内容,然后几乎立即忘记它。

我建议有这个问题的每个人只检查引用日志(git reflog),仅此而已。 一旦您看到所有提交的列表,就有一百种方法可以找到您正在寻找的提交并挑选它或从中创建分支。 在此过程中,您将了解 reflog 以及各种基本 git 命令的有用选项。

Why do people ask this question? Because they don't yet know about or understand the reflog.

Most answers to this question give long commands with options almost nobody will remember. So people come into this question and copy paste whatever they think they need and forget it almost immediately after.

I would advise everyone with this question to just check the reflog (git reflog), not much more than that. Once you see that list of all commits there are a hundred ways to find out what commit you're looking for and to cherry-pick it or create a branch from it. In the process you'll have learned about the reflog and useful options to various basic git commands.

人心善变 2024-07-12 16:37:33

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

  • 首先运行: git fsck --unreachable | findstr "commit"
  • 将输出复制到记事本
  • 查找用 start cmd /k git show 替换“unreachable commit”

将如下所示:

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

  • 另存为 .bat 文件并运行它,
  • 脚本将打开一堆命令窗口,显示每个提交(
  • 如果您找到了要查找的提交),运行: git stash apply (your hash)

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

I couldn't get any of the answers to work on Windows in a simple command window (Windows 7 in my case). awk, grep and Select-string weren't recognized as commands. So I tried a different approach:

  • first run: git fsck --unreachable | findstr "commit"
  • copy the output to notepad
  • find replace "unreachable commit" with start cmd /k git show

will look something like this:

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

  • save as a .bat file and run it
  • the script will open a bunch of command windows, showing each commit
  • if you found the one you're looking for, run: git stash apply (your hash)

may not be the best solution, but worked for me

尹雨沫 2024-07-12 16:37:33

当您没有可用的 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”进入下一个差异。

I want to add to the accepted solution another good way to go through all the changes, when you either don't have gitk available or no X for output.

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

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

Then you get all the diffs for those hashes displayed one after another. Press 'q' to get to the next diff.

南风几经秋 2024-07-12 16:37:33

亚里士多德接受的答案将显示所有可到达的提交,包括非存储类提交。 过滤掉噪音:

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“我新创建的存储”),这将覆盖默认的“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

The accepted answer by Aristotle will show all reachable commits, including non-stash-like commits. To filter out the noise:

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

This will only include commits which have exactly 3 parent commits (which a stash will have), and whose message includes "WIP on".

Keep in mind, that if you saved your stash with a message (e.g. git stash save "My newly created stash"), this will override the default "WIP on..." message.

You can display more information about each commit, e.g. display the commit message, or pass it to 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
走走停停 2024-07-12 16:37:33

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

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

如果您为存储提供了标题,请在命令末尾替换 -grep=WIP 中的“WIP”包含消息的一部分,例如 -grep=Tesselation

该命令正在 grep 查找“WIP”,因为存储的默认提交消息的格式为 WIP on mybranch: [previous-commit-hash] 上一次提交的消息。

当您找到提交时,使用 git stash apply应用它

To get the list of stashes that are still in your repository, but not reachable any more:

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

If you gave a title to your stash, replace "WIP" in -grep=WIP at the end of the command with a part of your message, e.g. -grep=Tesselation.

The command is grepping for "WIP" because the default commit message for a stash is in the form WIP on mybranch: [previous-commit-hash] Message of the previous commit.

When you have found the commit, apply it with git stash apply <commit_hash>

我做我的改变 2024-07-12 16:37:33

只是想提及已接受的解决方案中的这一补充。 当我第一次尝试这个方法时,这对我来说并不是很明显(也许应该是),但是要应用哈希值中的存储,只需使用“git stash apply”:

$ git stash apply ad38abbf76e26c803b27a6079348192d32f52219

当我刚接触 git 时,这不是我不清楚,我正在尝试“git show”、“git apply”、“patch”等的不同组合。

Just wanted to mention this addition to the accepted solution. It wasn't immediately obvious to me the first time I tried this method (maybe it should have been), but to apply the stash from the hash value, just use "git stash apply ":

$ git stash apply ad38abbf76e26c803b27a6079348192d32f52219

When I was new to git, this wasn't clear to me, and I was trying different combinations of "git show", "git apply", "patch", etc.

乜一 2024-07-12 16:37:33

我来这里寻找的是如何真正取回藏匿的东西,无论我检查了什么。 特别是,我隐藏了一些东西,然后签出旧版本,然后弹出它,但在那个较早的时间点,隐藏的内容是无操作的,所以隐藏的消失了; 我不能仅仅执行 git stash 来将其推回到堆栈上。 这对我有用:

$ git checkout somethingOld
$ git stash pop
...
nothing added to commit but untracked files present (use "git add" to track)
Dropped refs/stash@{0} (27f6bd8ba3c4a34f134e12fe69bf69c192f71179)
$ git checkout 27f6bd8ba3c
$ git reset HEAD^    # Make the working tree differ from the parent.
$ git stash # Put the stash back in the stack.
Saved working directory and index state WIP on (no branch): c2be516 Some message.
HEAD is now at c2be516 Some message.
$ git checkout somethingOld # Now we are back where we were.

回想起来,我应该使用 git stash apply ,而不是 git stash pop 。 我正在做一个bisect并且有一个小补丁,我想在每个bisect步骤中应用它。 现在我正在这样做:

$ git reset --hard; git bisect good; git stash apply
$ # Run tests
$ git reset --hard; git bisect bad; git stash apply
etc.

What I came here looking for is how to actually get the stash back, regardless of what I have checked out. In particular, I had stashed something, then checked out an older version, then poped it, but the stash was a no-op at that earlier time point, so the stash disappeared; I couldn't just do git stash to push it back on the stack. This worked for me:

$ git checkout somethingOld
$ git stash pop
...
nothing added to commit but untracked files present (use "git add" to track)
Dropped refs/stash@{0} (27f6bd8ba3c4a34f134e12fe69bf69c192f71179)
$ git checkout 27f6bd8ba3c
$ git reset HEAD^    # Make the working tree differ from the parent.
$ git stash # Put the stash back in the stack.
Saved working directory and index state WIP on (no branch): c2be516 Some message.
HEAD is now at c2be516 Some message.
$ git checkout somethingOld # Now we are back where we were.

In retrospect, I should have been using git stash apply not git stash pop. I was doing a bisect and had a little patch that I wanted to apply at every bisect step. Now I'm doing this:

$ git reset --hard; git bisect good; git stash apply
$ # Run tests
$ git reset --hard; git bisect bad; git stash apply
etc.
許願樹丅啲祈禱 2024-07-12 16:37:33

要在终端中查看提交,只过滤我们关心的提交:

git log --oneline --all --grep="^WIP on .*: [a-f0-9]\+" --grep="^On [^ ]*:" --grep="^index on [^ ]*:" $( env LANG=C git fsck --no-reflog | awk '/dangling commit/ {print $3}' )

这是基于 Aristotle Pagaltzis 的答案。

To see the commits in terminal, only filtering the ones we care about we can use:

git log --oneline --all --grep="^WIP on .*: [a-f0-9]\+" --grep="^On [^ ]*:" --grep="^index on [^ ]*:" $( env LANG=C git fsck --no-reflog | awk '/dangling commit/ {print $3}' )

This is based on Aristotle Pagaltzis answer.

暮倦 2024-07-12 16:37:33

要仅查看存储提交、它们附加的位置以及其内容是什么

结果示例

Checking object directories: 100% (256/256), done.
2022-08-31 10:20:46 +0900 8d02f61 WIP on master: 243b594 add css
A       favicon.ico

命令

git fsck --dangling | awk '/dangling commit/ {print $3}' | xargs -L 1 git --no-pager show -s --format="%ct %h" | sort | awk '{print $2}' | { while read hash; do status=$(git stash show $hash --name-status 2>/dev/null); if (( $? == 0 )); then git show $hash -s --format="%C(green)%ci %C(yellow)%h %C(blue)%B"; echo "$status"; fi; done; }
  • 要查看完整哈希,请将 %h 更改为 %H
  • 要减少时间,请使用 tail fsck,例如git fsck --dangling | git fsck --dangling | git fsck --dangling | git fsck --dangling | 尾-100 | awk ...

恢复样本
输入图像描述这里

To see only stash commits, where they attached, and what their contents are

result sample

Checking object directories: 100% (256/256), done.
2022-08-31 10:20:46 +0900 8d02f61 WIP on master: 243b594 add css
A       favicon.ico

command

git fsck --dangling | awk '/dangling commit/ {print $3}' | xargs -L 1 git --no-pager show -s --format="%ct %h" | sort | awk '{print $2}' | { while read hash; do status=$(git stash show $hash --name-status 2>/dev/null); if (( $? == 0 )); then git show $hash -s --format="%C(green)%ci %C(yellow)%h %C(blue)%B"; echo "$status"; fi; done; }
  • To see full hash, change %h to %H
  • To reduce time, tail fsck like git fsck --dangling | tail -100 | awk ...

recover sample
enter image description here

水中月 2024-07-12 16:37:33

使用以下步骤恢复它:

  1. 识别已删除的存储哈希代码:

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

  2. Cherry Pick the Stash:

    gitcherry-pick -m 1 $stash_hash_code

  3. 解决冲突(如果有)使用:

    git mergetool

此外,如果您使用 gerrit,则可能会遇到提交消息问题。 请在执行下一个替代方案之前存储您的更改:

  1. 使用硬重置到之前的提交,然后重新提交此更改。
  2. 您还可以隐藏更改、变基并重新提交。

Recovered it by using following steps:

  1. Identify the deleted stash hash code:

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

  2. Cherry Pick the Stash:

    git cherry-pick -m 1 $stash_hash_code

  3. Resolve Conflicts if any using:

    git mergetool

Additionally you might be having issues with commit message if you are using gerrit. Please Stash your changes before following next alternatives:

  1. Use hard reset to previous commit and then recommit this change.
  2. You may also stash the change, rebase and recommit.
怎樣才叫好 2024-07-12 16:37:33

Github Desktop

如果您使用 Github Desktop 存储了更改,并且意外删除了存储的更改,那么您可以运行以下命令来搜索悬空存储提交(基于 这个答案):

注意:如果使用 Windows,请使用 Git Bash(与 git 安装一起安装)运行命令,

git log --graph --oneline --decorate --all $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' ) | grep 'GitHub_Desktop'

您将获得一个提交列表,例如:

| *   b7f1b023 On main: !!GitHub_Desktop<main>
| * 7e949012 On main: !!GitHub_Desktop<main>
| * 7de9b9ca On main: !!GitHub_Desktop<main>

获取提交列表中第一个的。 在上面的示例中,它将是 b7f1b023 并运行以下命令:

git stash apply b7f1b023

这将恢复您的更改。 如果没有,您可以尝试输出中的其他提交。

Github Desktop

If you stashed your changes using Github Desktop, and accidentally removed your stashed changes, then you can run the following to search for dangling stash commit (based on this answer):

Note: If using Windows, run the commands using Git Bash (which is installed alongside git installation)

git log --graph --oneline --decorate --all $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' ) | grep 'GitHub_Desktop'

You will get a list of commits like:

| *   b7f1b023 On main: !!GitHub_Desktop<main>
| * 7e949012 On main: !!GitHub_Desktop<main>
| * 7de9b9ca On main: !!GitHub_Desktop<main>

Get the commit of the first one in the list. In the above example, it will be b7f1b023 and run the following:

git stash apply b7f1b023

This will recover your changes. If it doesn't, you can try other commits in the output.

马蹄踏│碎落叶 2024-07-12 16:37:32

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

git stash apply $stash_hash

或者,你可以为它创建一个单独的分支,

git branch recovered $stash_hash

之后,你可以使用所有普通工具做任何你想做的事情。 完成后,只需将树枝吹走即可。

查找哈希

如果您刚刚弹出它并且终端仍然打开,您将 屏幕上仍然有 git stash pop 打印的哈希值(谢谢,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}' )

...或参见 emragins 的答案(如果使用 Windows 版 PowerShell)。

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

如果您更喜欢控制台上的漂亮图表而不是单独的 GUI 应用程序,则可以将其中的 gitk 替换为 git log --graph --oneline --decorate 之类的内容。

要发现存储提交,请查找以下形式的提交消息

:       某个分支上的 WIPcommithash 一些旧的提交消息

注意:提交消息仅采用这种形式(以“WIP on”开头),如果当您执行git stash时,您没有提供消息。

Once you know the hash of the stash commit you dropped, you can apply it as a stash:

git stash apply $stash_hash

Or, you can create a separate branch for it with

git branch recovered $stash_hash

After that, you can do whatever you want with all the normal tools. When you’re done, just blow the branch away.

Finding the hash

If you have only just popped it and the terminal is still open, you will still have the hash value printed by git stash pop on screen (thanks, Dolda).

Otherwise, you can find it using this for Linux, Unix or Git Bash for Windows:

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

...or using PowerShell for Windows:

git fsck --no-reflog | select-string 'dangling commit' | foreach { $_.ToString().Split(" ")[2] }

This will show you all the commits at the tips of your commit graph which are no longer referenced from any branch or tag – every lost commit, including every stash commit you’ve ever created, will be somewhere in that graph.

The easiest way to find the stash commit you want is probably to pass that list to gitk:

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

...or see the answer from emragins if using PowerShell for Windows.

This will launch a repository browser showing you every single commit in the repository ever, regardless of whether it is reachable or not.

You can replace gitk there with something like git log --graph --oneline --decorate if you prefer a nice graph on the console over a separate GUI app.

To spot stash commits, look for commit messages of this form:

        WIP on somebranch: commithash Some old commit message

Note: The commit message will only be in this form (starting with "WIP on") if you did not supply a message when you did git stash.

我爱人 2024-07-12 16:37:32

如果您没有关闭终端,只需查看 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

将其作为分支还可以让您自由地操作它; 例如,挑选它或合并它。

If you didn't close the terminal, just look at the output from git stash pop and you'll have the object ID of the dropped stash. It normally looks like this:

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

(Note that git stash drop also produces the same line.)

To get that stash back, just run git branch tmp 2cae03e, and you'll get it as a branch. To convert this to a stash, run:

git stash apply tmp
git stash

Having it as a branch also allows you to manipulate it freely; for example, to cherry-pick it or merge it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文