How to recover a dropped stash in Git?

前端 未结 19 1703
别跟我提以往
别跟我提以往 2020-11-22 01:42

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

相关标签:
19条回答
  • 2020-11-22 02:03

    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
    
    0 讨论(0)
  • 2020-11-22 02:06

    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
    
    0 讨论(0)
  • 2020-11-22 02:06

    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.
    0 讨论(0)
  • 2020-11-22 02:07

    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
    
    0 讨论(0)
  • 2020-11-22 02:08

    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.

    0 讨论(0)
  • 2020-11-22 02:08

    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

    0 讨论(0)
提交回复
热议问题