2

I've got a broken stash:

% git stash drop            
fatal: log for refs/stash is empty
% cat .git/logs/refs/stash
%

It does show up in git log --all, though:

% lal

*   f32cdce - (HEAD -> develop, origin/develop) (44 minutes ago) <Williams, Ken>
|\  
| * 05cc7d3 - (3 weeks ago) <Ken Williams>
| * 6d9c8ae - (3 weeks ago) <Ken Williams>
| | * 3fb311d - (refs/stash) (3 weeks ago) <Ken Williams>
| |/| 
| | * 19be16e - (3 weeks ago) <Ken Williams>
| |/  
| * ffea5e2 - (i2) (9 weeks ago) <Ken Williams>

(lal is my alias for git log --graph --pretty=format:'%h -%C(yellow)%d%Creset %Cgreen(%ad) %C(bold blue)<%an>%Creset' --all.)

I did a git stash apply 3fb311d, so I've got the content of the stash secured. Now, how can I remove that refs/stash from the tree so it doesn't keep complaining?

EDIT

Even after deleting the refs/stash reference as suggested by @mark-adelsberger, the commits show up in the history listing:

% lal

*   f32cdce - (HEAD -> develop, origin/develop) (31 hours ago) <Williams, Ken>
|\  
| * 05cc7d3 - (3 weeks ago) <Ken Williams>
| * 6d9c8ae - (3 weeks ago) <Ken Williams>
| | * 3fb311d - (3 weeks ago) <Ken Williams>
| |/| 
| | * 19be16e - (3 weeks ago) <Ken Williams>
| |/  
| * ffea5e2 - (i2) (9 weeks ago) <Ken Williams>
| * 199af47 - (9 weeks ago) <Ken Williams>
...

This is using Git 2.29.0 (homebrew) on OS X 10.15.7.

Ken Williams
  • 22,756
  • 10
  • 85
  • 147
  • `rm .git/refs/stash` ? – matt Nov 09 '20 at 17:51
  • @matt I don't have a `.git/refs/stash` file. I'm not sure where the stash info is being stored. – Ken Williams Nov 09 '20 at 17:59
  • I assume you also did `rm .git/logs/refs/stash` ? Together, those two commands blow away your stashes. – matt Nov 09 '20 at 18:02
  • @matt that does not seem to be true, even after removing both those files (and `find .git | grep stash` returns nothing) the stash is visible in `git lg --all`. – Ken Williams Nov 09 '20 at 18:31
  • The question is not what shows up in `git lg --all`. What you asked us to solve is that `git stash drop` barfs. If you do what I suggested and the barfing stops, my work here is done! :) – matt Nov 09 '20 at 18:42
  • That's a bit curious, because even if the reflog for `refs/stash` is empty, the `refs/stash` ref itself should get deleted. And, [after you manually deleted it](https://stackoverflow.com/questions/64756516/git-remove-broken-stash#comment114497076_64757207) it should stop showing up entirely. I wonder: do you have any added work-trees? – torek Nov 10 '20 at 00:48
  • @torek nope, no work trees. – Ken Williams Nov 10 '20 at 23:11

1 Answers1

3

Update - Added notes at end based on edited question


If .git/refs/stash is empty (or non-existant) yet git log shows a refs/stash, then I would suspect the stash ref got added to your packed-refs file somehow.

You can confirm the existence of the ref (regardless of its representation on disk) with

git for-each-ref refs/stash

and if this shows refs/stash (as I think it will), then you can delete the ref with

git update-ref -d refs/stash

As a reminder this is a potentially destructive command; in the specific case where you know you either have saved a ref to that data, or no longer want it, then it's fine.


So it's not clear to me what would cause log to report a commit that doesn't seem to be reachable (based on the graph and on the lack of refnames on that particular commit). If I had a repo in that state I think I could figure out what's going on, but I really don't know how to reproduce the symptom.

My best suggestion is to do

git for-each-ref |grep 3fb311d

to see if for some reason a ref just isn't being named in the log. IF that shows nothing, another idea is just

git for-each-ref

Or see if

git fsck

tells you anything useful. If any of this turns up more information, I'll be happy to look at it and update with more suggestions.

Mark Adelsberger
  • 42,148
  • 4
  • 35
  • 52
  • Thanks Mark, `git for-each-ref refs/stash` does indeed give me a hash (starting with `3fb311d` so it's consistent with my log output). I deleted it with `update-ref`, but it still shows (with no reference name) in my `git lg --all` output. Why would that still show up, with no named references to it? – Ken Williams Nov 09 '20 at 18:31
  • @KenWilliams Is the 3fb311d commit checked out at the time you generate the output? If it isn't showing any named ref, and it doesn't have any children that lead to a named ref, and it isn't checked out, then I can't think of a reason it would be in the log output – Mark Adelsberger Nov 09 '20 at 18:52
  • Nope, `3fb311d` isn't checked out, it appears off to the side of the tree just like I showed in my original question, but now without the `refs/stash` name - I'll add an edit to the question to show that. – Ken Williams Nov 10 '20 at 23:13
  • @KenWilliams - sounds like you have a repo in an unusual state. I don't know how to reproduce it; added a few shot-in-the-dark ideas you could try, in order to gather more info – Mark Adelsberger Nov 11 '20 at 04:13
  • Thanks for sticking with it! I did find a `refs/replace` reference by doing `git for-each-ref |grep 3fb311d`: `3fb311d7a9b1fb7d0d394ad723747b23d83f3ce9 commit refs/replace/da1018741f5cea52e4b139d8f0ca93f4d1c3d12c`. Certainly didn't create that myself. – Ken Williams Nov 12 '20 at 16:44
  • `git fsck` reports nothing interesting. – Ken Williams Nov 12 '20 at 16:44
  • That looks like it came from `git replace`; see https://git-scm.com/docs/git-replace . It is *very* odd to have a stash referenced in that way. – Mark Adelsberger Nov 12 '20 at 19:12
  • Yes indeed. I've heard of `git replace` but never used it, certainly not in this repo. The only slightly wonky thing I ever did in this repo was add a second remote, cherry-pick some commits from it, then remove that remote. – Ken Williams Nov 12 '20 at 21:16
  • ACTUALLY, I do recall doing some `git filter-repo --path-rename foo:bar` stuff after cherry-picking, to get the content in the directory I wanted. It looks like `filter-repo` might create some replace-refs, maybe that's related? – Ken Williams Nov 12 '20 at 21:19
  • Could be. I haven't worked much with `filter-repo` yet. It's a little curious why it would perform any transformation at all on a stash, but depending on what commands were given maybe it didn't know better. I wonder if the stash ref getting packed could also be related... but speculation aside, the question is - do you at this point know how to get your repo into an acceptable state, and is your question answered? – Mark Adelsberger Nov 13 '20 at 04:41
  • I've got myself into the same situation, but I've never used `git replace` or `filter-repo`, or added other remotes. – Mark Jeronimus Aug 14 '21 at 21:47
  • I finally found something that worked for me: `git fsck --full` – Mark Jeronimus Aug 14 '21 at 22:02