Question

I have added a directory with git add and realized that there are wrong files in it, so I used git reset --hard to go back to the latest commit but I didn't know that git would also delete those added files in the working copy.

Does anyone know how I undo this?

Was it helpful?

Solution

When you git add a file, it is added to the object database and to the index. Running git reset updated the index and the working directory, but it did not remove those files from the object database. They remain as unrooted ("dangling") objects. You can run the git filesystem checker, git fsck to see what items are "dangling". You should see a report like:

% git fsck
dangling blob 1ff0c423042b46cb1d617b81efb715defbe8054d
dangling blob 1bc915c5cb7185a9438de28a7b1a7dfe8c01ee7f
dangling blob a8c86221b400b836010567cc3593db6e96c1a83a
dangling blob 46ff0854663aeb2182b9838c8da68e33ac23bc1e
dangling blob 21a96a98ed84d45866e1de6e266fd3a61a4ae9dc
... etc ...

If you also happen to have a dangling tree, you may be able to restore the filename to blob ID mappings. If you have some dangling tree:

dangling tree 57623d711c18d819831f24a9456f0660e9dbe596

Then you can display the tree contents by running the git ls-tree command:

% git ls-tree 57623d711c18d819831f24a9456f0660e9dbe596
100644 blob 21a96a98ed84d45866e1de6e266fd3a61a4ae9dc file1.txt
100644 blob 46ff0854663aeb2182b9838c8da68e33ac23bc1e file2.txt

This indicates that blob 46ff0854663aeb2182b9838c8da68e33ac23bc1e was added originally as file1.txt. However, it is most likely that you did not get trees added to the object database and you will need to examine each file to determine where you wish to save it.

You can get the blob's contents using the git cat-file command. For example, to save it to recovered.bak:

% git cat-file blob 46ff0854663aeb2182b9838c8da68e33ac23bc1e  > recovered.bak

OTHER TIPS

You can run the git filesystem checker, git fsck to see what items are "dangling".

Do so with a recent Git: The resolve-undo information in the index was not protected against GC, which has been corrected with Git 2.38 (Q3 2022).

See commit e0ad139 (11 Jul 2022), and commit 5a5ea14 (09 Jun 2022) by Junio C Hamano (gitster).
(Merged by Junio C Hamano -- gitster -- in commit 418aef9, 19 Jul 2022)

revision: mark blobs needed for resolve-undo as reachable

The resolve-undo extension was added to the index in cfc5789 ("resolve-undo: record resolved conflicts in a new index extension section", 2009-12-25, Git v1.7.0-rc0 -- merge).
This extension records the blob object names and their modes of conflicted paths when the path gets resolved (e.g. with "git add"(man)), to allow "undoing" the resolution with "checkout -m path".
These blob objects should be guarded from garbage-collection while we have the resolve-undo information in the index (otherwise unresolve operation may try to use a blob object that has already been pruned away).

But the code called from mark_reachable_objects() for the index forgets to do so.
Teach add_index_objects_to_pending() helper to also add objects referred to by the resolve-undo extension.

Also make matching changes to "fsck", which has code that is fairly similar to the reachability stuff, but have parallel implementations for all these stuff, which may (or may not) someday want to be unified.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top