Keywords: Git stash recovery | Dangling commits | git fsck command
Abstract: This article provides a comprehensive exploration of methods to recover stash commits that have been removed via git stash pop in Git. It begins by explaining the fundamental principles of Git's stash mechanism, including the roles of .git/refs/stash and .git/logs/refs/stash. The core focus is on using the git fsck command to locate dangling commits, with specific commands provided for both Linux/Unix and Windows PowerShell environments. The article details how to identify stash commits through visualization tools like gitk or git log, along with strategies for applying recovered stashes and branch management. Additional coverage includes quick recovery methods when the terminal remains open and important considerations for practical application scenarios.
Overview of Git Stash Mechanism
Git's stash functionality preserves changes from the working directory and staging area by creating special commits. When git stash is executed, Git generates a commit object whose reference is stored in .git/refs/stash, with related logs recorded in .git/logs/refs/stash. However, when a stash is applied and removed using git stash pop, these references are deleted, but the corresponding commit objects remain in Git's object database.
Finding Dangling Commits
To recover a dropped stash, the first step is to locate the corresponding commit hash. Git's fsck (file system check) command can identify dangling objects that are no longer referenced by any pointers.
In Linux, Unix, or Git Bash for Windows environments, use the following command:
git fsck --no-reflog | awk '/dangling commit/ {print $3}'
In Windows PowerShell environments, the equivalent command is:
git fsck --no-reflog | select-string 'dangling commit' | foreach { $_.ToString().Split(" ")[2] }
These commands output a list of all dangling commit hashes, including every stash commit ever created in the repository's history.
Visual Identification of Stash Commits
To accurately identify the target stash commit from the numerous dangling commits, graphical tools can be used for filtering.
Using the gitk graphical interface tool:
gitk --all $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' )
Alternatively, using command-line graphical display:
git log --graph --oneline --decorate $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' )
When browsing the commit history, focus on commits with message formats like WIP on <branch-name>: <commit-hash> <original-commit-message>. It is important to note that this specific message format only appears when git stash is executed without providing a custom message.
Recovery and Application of Stashes
Once the target stash commit hash is identified, there are multiple ways to recover and utilize these changes.
Directly apply the stash changes:
git stash apply <stash-hash>
Create a branch for management:
git branch recovered <stash-hash>
The branch creation method offers greater flexibility, allowing the use of all standard Git tools to manipulate the changes, such as cherry-picking or merging. After completing operations, the branch can be simply deleted.
Special Case Handling
If the terminal session has not been closed and the output from git stash pop or git stash drop is still visible, the stash commit hash can be directly obtained from the output. The typical output format is:
Dropped refs/stash@{0} (2ca03e22256be97f9e40f08e6d6773c7d41dbfd1)
In this scenario, the recovery process becomes significantly more straightforward.
Technical Details Explanation
Git's object database design ensures that all created commits are permanently stored until cleaned up by garbage collection mechanisms. This means that even when references are deleted, the actual commit objects remain in the .git/objects directory, providing the possibility for recovery operations.
In practice, it is recommended to periodically clean up unnecessary dangling objects to optimize repository performance. However, this persistent storage mechanism serves as a valuable safety net when important changes need to be recovered.