John Little
John Little

Reputation: 12343

git pop failed with "error: could not restore untracked files from stash"

I have done about 2 months work locally against main branch (without committing or staging anything). This included adding new (untracked) files and modifying existing tracked files.

Then I wanted to check something on the main branch without my changes so did:

git stash -all

Expecting it to stash both my tracked and untracked file changes.

I then did

git stash pop

To get my changes back, and got thousands of errors:

.project already exists, no checkout
all/.project already exists, no checkout
all/.settings/org.eclipse.wst.common.component already exists, no checkout
all/target/vault-work/META-INF/MANIFEST.MF already exists, no checkout
all/target/vault-work/META-INF/vault/config.xml already exists, no checkout
all/target/vault-work/META-INF/vault/filter.xml already exists, no checkout
all/target/vault-work/META-INF/vault/properties.xml already exists, no checkout
all/target/vault-work/META-INF/vault/settings.xml already exists, no checkout
core/.project already exists, no checkout
core/target/classes/META-INF/MANIFEST.MF already exists, no checkout
core/target/classes/OSGI-INF/com.xx.aem.core.filters.CorrelationLoggingFilter.xml already exists, no checkout
core/target/classes/OSGI-INF/com.xx.aem.core.filters.LinkHeaderFilter.xml already exists, no checkout
core/target/classes/OSGI-INF/com.xx.aem.core.filters.LoggingFilter.xml already exists, no checkout

and ending in:

ui.content/target/vault-work/META-INF/vault/settings.xml already exists, no checkout
ui.frontend/.project already exists, no checkout
ui.tests/.project already exists, no checkout
error: could not restore untracked files from stash
The stash entry is kept in case you need it again.

Surprisingly, when looking at the state of the local code, it does seem to have created the new files. But none of the changed files are there. So the error says it could not restore untracked files, but it appears to have, but it has not recovered the changes I made to existing files.

Summary:

  1. I had changed files and new (untracked files) from main.
  2. I did "git stash -all"
  3. This got me back to main without my changes.
  4. I then did "git pop", expecting to be back to 1.
  5. got thousands of errors for no apparent reason.
  6. None of my changes to files are there.
  7. My new, untrack files do see to be there, despite it saying it could not restore them.

How do I get back all the changes I did to existing files?

Any help appreciated.

Note: I have recently noticed that git stash --all (which was recommended on a post in order to stash tracked and untracked files) may also (bizarrely) stash ignored files - this could be the crux of the problem.

If I do

git stash show

I get

bob@MacBook-Pro eyas-web % git stash show
 .../aem/core/filters/xx.java |  25 ++-
 .../models/xxx/response/x.java   |  18 --
 .../xx/aem/core/models/xx/Player.java         |  14 ++
 .../xx/aem/core/services/xx.java       |  31 +++
 .../services/impl/xx.java  |   2 +-
 .../core/services/impl/xx.java |   6 +
 .../aem/core/services/impl/xx.java   | 212 ++++++++++++++++++++-
 pom.xml                                            |  18 --
 8 files changed, 282 insertions(+), 44 deletions(-)

I need to figure out how to get the "8 files changed" back from the stash, along side the new untracked files which do seem to have been restored.

One idea might be to try to remove all the ignored files, then do git stash pop again. However, looking at the man pages for "git clean -xdf", it doesn't say if -x also removes the necessary git files as well as the ignored files we added (such as project config files).

Any ideas how to fix this?

I noticed this post: How do you stash an untracked file?

Which says: "git stash -u Warning, doing this will permanently delete your files if you have any directory/ entries in your gitignore file."

This seems very bad, and may be related to my issue.

Upvotes: 2

Views: 1331

Answers (4)

John Little
John Little

Reputation: 12343

I found a great and simple solution:

  1. duplicate (using macOs duplicate finder option) the entire project directory (5GB) as a backup just in case.
  2. git clean -xfd
  3. git stash apply

Now I seem to be back where I started. The clean -xfd removes the untracked files and folders, which includes all those ignored by git ignore, as well as my work. This was a bit of a gamble as the documentation implies that this command also removes the git control files, but it doesn't seem to.

The "stash apply" then creates all the untracked files, including the ignored files, my work, then updates my modified tracked files.

Upvotes: 1

LeGEC
LeGEC

Reputation: 51850

note : git stash apply first tries to restore your indexed and tracked files, and only then your untracked files. If it reaches the "untracked files" step, it should indicate that the first part was applied without conflicts.


git stash apply can be used with any commit that looks like a stash. So you can create a stash-like commit which contains only the index and the tracked files, and use that one to reapply changes on your tracked files only.

  • with the -u or -a option, git stash will create a 3 legged commit

You can view that by running git log --oneline --graph stash

$ git log --graph --oneline stash
*-.   db814f6 (refs/stash) WIP on master: 06ffba6 create c.txt  # the worktree
|\ \  
| | * 27b820c untracked files on master: 06ffba6 create c.txt   # the untracked files
| * e59f7fb index on master: 06ffba6 create c.txt               # the index
|/  
* 06ffba6 create c.txt                                          # the active commit
* df9858f create b.txt
...
  • you can create a stash-like commit with only 2 legs (e.g : the active commit and the index) :
# create the commit :
git commit-tree stash^{tree} -p stash^ -p stash^2 -m "my stash"

# for convenience : give a name to that commit
git tag mystash <sha output above>
  • you can now run git stash apply --index mystash, and you will have feedback only on your indexed/tracked files (e.g : "it worked / conflicts occurred")

  • you can use git restore or git checkout to get your untracked files back from stash^3 :

# restore selected files from that stash entry :
git restore --overlay -W -s stash^3 -- that/file that/dir/

a word of warning: if you are using git restore for files which are not tracked or not committed, you can accidentally remove data from your disk which isn't stored within git. You would be better off working on a clean worktree.


I wrote all the above command by referring to the stash commit, which is the topmost stash, but if you have to run git stash again to stash away more changes, then the target you want is not the topmost stash anymore.

You can replace stash in all commands above by stash@{1} or stash@{nn}, or by the sha of the stash commit you want to work with.

Upvotes: 1

jschnasse
jschnasse

Reputation: 9498

How do I get back all the changes I did to existing files?

I would try git stash branch:

  1. Backup your whole directory (just in case).
  2. git stash branch my-stash-in-a-branch This should bring back everything you've stashed. Even untracked/ignored stuff from git stash --all will be recovered.
  3. Now do something like git rebase -i master to get in sync with your mainline.

PS: I cross my fingers for you that your stash is not already empty. Prefer git stash apply over git stash pop in unclear situations.

Upvotes: 2

Yoichi Nakayama
Yoichi Nakayama

Reputation: 774

I then did a build and deployment,

These steps may have created new untracked files in your working tree. And I think those untracked files are blocking git stash pop.

Check working tree status by git status. If you see unwanted untracked files, use git clean to remove them, then git stash pop.

Upvotes: 1

Related Questions