Home > front end >  All my modifications gone after git stash
All my modifications gone after git stash

Time:07-25

I was working on the main branch, then I decided to create a new branch called test-branch. I tried git checkout feature first which warned me to stash or commit my changes. I stashed them using git stash save latest modification and then I went to test-branch using git checkout -b test-branch. I was trying to add all files (not ignoring any) and commit to the branch. So I deleted everyting from .gitignore. After running git add ., I came back to main without committing to test-branch. I deleted that branch using git branch -D test-branch. And then I used git stash apply in main. Now my code has gone to the last commit version and all the modifications I did after that commit exist no more. What do I do now ?

Before swtiching branches

PS C:\Users\Administrator\Desktop\projects\songs> git checkout feature
error: Your local changes to the following files would be overwritten by checkout:
        .gitignore
        app.py
        music.db
        static/css/styles.css
        templates/favorites.html
        templates/layout.html
Please commit your changes or stash them before you switch branches.

PS C:\Users\Administrator\Desktop\projects\songs> git stash save "latest modification"
Saved working directory and index state On main: latest modification
Unlink of file 'music.db' failed. Should I try again? (y/n) y
fatal: Could not reset index file to revision 'HEAD'.

After switching branches

PS C:\Users\Administrator\Desktop\projects\songs> git checkout -b test-branch
Switched to a new branch 'test-branch'

PS C:\Users\Administrator\Desktop\projects\songs> git st
 M music.db
?? static/scripts/downloader.js
?? test/

PS C:\Users\Administrator\Desktop\projects\songs> git add .

I then came back again to main

PS C:\Users\Administrator\Desktop\projects\songs> git checkout main
Switched to branch 'main'
M       .gitignore
M       music.db
A       static/scripts/downloader.js
A       test/a.exe
A       test/ipvalidator.exe
A       test/nextvalidator.c
A       test/nextvalidator.exe
Your branch is up to date with 'origin/main'.

PS C:\Users\Administrator\Desktop\projects\songs> git branch -D "test-branch"
Deleted branch test-branch (was 08f1d8e).

Then I applied the stash and my changes are gone


PS C:\Users\Administrator\Desktop\projects\songs> git stash apply
error: Your local changes to the following files would be overwritten by merge:
        .gitignore
Please commit your changes or stash them before you merge.
Aborting

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   music.db
        new file:   static/scripts/downloader.js
        new file:   test/a.exe
        new file:   test/ipvalidator.exe
        new file:   test/nextvalidator.c
        new file:   test/nextvalidator.exe

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   .gitignore

Untracked files:
        __pycache__/
        flask_session/
        improvements.txt
        
        run.ps1
        static/downloads/
        templates/test.html
        test.py
        venv/

Edit:

As per @ElderFuthark 's request, I ran git stash show --stat and got the following:

PS C:\Users\Administrator\Desktop\projects\songs>  git stash show --stat
 .gitignore                 |   4   --
 app.py                     |  11        ----
 music.db                   | Bin 69632 -> 86016 bytes
 static/css/musicPlayer.css |   1  
 static/css/styles.css      |   4    -
 templates/favorites.html   |   2   
 templates/layout.html      |   8       --
 templates/play.html        |  27                    --------
 8 files changed, 40 insertions( ), 17 deletions(-)

CodePudding user response:

Long: part 2 of 2: what you can do now

(see also part 1)

The short version of this is:

  • what you have available through Git itself, to restore files, is whatever's in commits, plus anything you can commit right now from Git's index;
  • what you have available on your computer in general includes any untracked files and any backups you made with backup software (e.g., Time Machine on macOS).

These are the places to go to get files back.

Your git stash show --stat shows a diff from the commit I've been labeling K to the one in w:

git stash show --stat
 .gitignore                 |   4   --
 app.py                     |  11        ----
 music.db                   | Bin 69632 -> 86016 bytes
 static/css/musicPlayer.css |   1  
 static/css/styles.css      |   4    -
 templates/favorites.html   |   2   
 templates/layout.html      |   8       --
 templates/play.html        |  27                    --------

You also have, now, in your index, a version of music.db (probably matching that in the w commit here), and the Added files. You can git commit this or git stash again if you like, to make more commits. You still have your existing stash.

You can turn any stash into a branch with git stash branch. If there is valuable data in the existing stash, that's my general recommendation: once it's a normal everyday branch, you can use all of Git's tools with it.

If there's nothing valuable in Git's index and your working tree right now, you can use git reset --hard HEAD to reset both of those.

Since there was a problem with music.db, you should find out why: there's probably a program that had, or still has, it open, preventing you from replacing the file. If you can terminate that program, or convince it to close the file, you can work on / with it again.

So, do each of these things—e.g., make a commit out of what you have now, if necessary and appropriate, fix whatever kept you from working with music.db, and/or turn the existing stash into a branch with git stash branch. If there's nothing valuable in the stash, drop the stash.

Using git stash branch

Before you can use git stash branch, you need to be in a "clean" state—that is, one where git status does not talk about changes that are to-be-committed and not-staged-for-commit. (Or, one where your git st short-status alias does not show any M, A, D, etc., files; ?? untracked files are sometimes OK.)

Then you can run:

git stash branch new-branch-for-stash

What this does is:

  • check out the parent of the i and w commits (that's commit K in my drawings here); and
  • use git stash apply --index to restore both the index and working tree states.

This almost always works (the exceptions include cases like "some program holds music.db open so that we can't patch it"; note that music.db is different between commit K and w here). It leaves you in a state where you can run git commit, or git add and git commit, or git commit followed by git add and git commit. Choose whichever you would like, to commit the changes you'd stashed, and get back to a "clean" git status (except, perhaps, for untracked files).

Untracked files are the usual problem here, especially when .gitignore has changed over time, because some files may actually be in some commits, when they shouldn't really be in those commits, and if you successfully check out such a commit, that file will now be in Git's index. Git will now want to remove the file if and when you switch from that commit to another commit that lacks the file.

The solution is usually the obvious trivial one: rename the untracked files out of the way, or entirely out of the working tree (which is also out of the way). That way, you still have the files and they are still not in the index. By using fresh names for them, they won't be clobbered by any commits where they were accidentally (or on purpose but incorrectly) stored.

For any files that aren't in Git, you'll need to restore them using some outside-Git mechanism.

CodePudding user response:

Long, so, part 1 of 2

(see part 2 for what you can do)

There are multiple things to learn here, and also multiple different steps to take to recover everything. There's overlap between the two but they're not exactly the same.

One thing I would suggest as a learning item is "don't use git stash" because it often makes a big mess.

  • Related