3

I was doing a rebase when some commit had conflicts. During resolving the conflicts I accidentally added all of my untracked files. Because I too don't keep track of untracked files I could not remember which files to unstage. Or which files where staged as part of the conflicting commit.

Instead of figuring it out, I decided to git rebase --abort hoping to just start over. However, those files that were mistakenly added have now disappeared.

I would like to understand what had happened. And why git rebase --abort does not restore my working tree to its original state. And if possible, where to find these files. Some of them have valuable work.

joegomain
  • 536
  • 1
  • 5
  • 22
  • git does not save the working tree in any way (except with `git stash`) – dan1st Jul 25 '23 at 09:50
  • 3
    You could get them back with some effort by checking dangling objects (blobs, to be more precise) in the DB if they were added at some point.... _however_, you will have to find the path of each one... and it's not like the only dangling objects will be those you are looking for. – eftshift0 Jul 25 '23 at 09:53
  • @eftshift0 Could you expand on that or point to where to learn please? – joegomain Jul 25 '23 at 09:57
  • There are probably maaaaaany answers (and maaaaaaany of them newer that this) but this should work fine as a starting point: https://stackoverflow.com/questions/9560184/recover-dangling-blobs-in-git – eftshift0 Jul 25 '23 at 09:59
  • An interesting question! I think it would require quite some logic for git to distinguish between "staged by the conflicting commit" and "staged by the user while resolving the conflict". Only then could the appropriate action be taken by `git rebase --abort`: Delete files staged by the conflicting commit but simply unstage files staged by the user. – SebDieBln Jul 25 '23 at 10:14
  • @SebDieBln that would be to `restore` any *new file* changes. – joegomain Jul 25 '23 at 16:05
  • It's not clear from your question whether you staged the files and then aborted, or if you staged and committed the files, and then aborted. Both cases will delete the untracked file. If you committed, see [knittl's answer](https://stackoverflow.com/a/76765546/184546). If you did not commit, then see @eftshift0's comments. – TTT Jul 25 '23 at 19:37
  • If you only staged without committing and now regret it, then I apologize in advance for this comment: Note that IMHO your issue is that "I too don't keep track of untracked files" combined with "Some of them have valuable work". – TTT Jul 25 '23 at 19:41
  • @TTT yeah, that's the underlying issue: "why am I not tracking valuable work?" ;-) Not the one at hand, nevertheless. – joegomain Jul 26 '23 at 03:19

1 Answers1

1

Nothing has been lost!

The Git reflog records all commits made on local branches ("references" or "refs" for short) and also for all commits that HEAD pointed to.

Run git reflog and you should see all commits made during your aborted rebase process. The reflog should contain an entry "rebase (abort): returning to ...".

Use git log or gitk to inspect this commit (or any other commit of the reflog) and then git branch hash-of-that-commit to create a new branch pointing to that commit. You can then switch to that branch to extract the files.

As to why the files were removed when aborting the rebase: Git only leaves untracked files alone during its operations. Once you tracked these files (intentionally or not), they became managed by Git. Switching branches or checking out different commits will remove (tracked) files from your working tree which are part of the "previous" commit but not part of the to-be-checked-out commit.

The good thing is that Git doesn't easily lose data that has been committed once.


If files never were committed, but the content of the file was staged (with git add), then it is still possible to recover the content, but it is a bit more work. Run git fsck to find any dangling blobs and then use git cat-file -p or git show with the object id of the respective blob. Once you have found the correct blob(s), redirect the output of cat-file/show to a file with the desired name. Repeat for all your files.

knittl
  • 246,190
  • 53
  • 318
  • 364
  • The added files did not reach any commit yet. Just staged. Then abort. This answer would apply had I indeed committed them. I had some luck with `git fsck` and able to find loss contents in some _dangling blob_ s. – joegomain Jul 26 '23 at 03:13
  • @joegomain this would sound indeed like a bug. When you say "did not commit", did you not run `git bisect --continue` either? The latter would still create a commit. Git shouldn't remove files from the working tree, simply because their contents were staged. I'd have to verify that locally though – knittl Jul 26 '23 at 06:19
  • 1
    Indeed, staging a file and then running `git reset --hard` removes the file from the working tree. I did not expect this (but I'm sure there's a reason for it …) – knittl Jul 26 '23 at 07:44